Skip to content

Commit 3d02a3e

Browse files
committed
Merge pull request #39 from AlexRiina/master
Fix how queryset-ish wasn't queryset-ish enough
2 parents ba358f7 + 30d1db2 commit 3d02a3e

File tree

5 files changed

+21
-75
lines changed

5 files changed

+21
-75
lines changed

django_object_actions/tests/test_utils.py

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
1-
from django.db.models.query import QuerySet
21
from django.test import TestCase
3-
from django.utils.unittest import expectedFailure
42

53
from example_project.polls.models import Poll
64

75
from ..utils import (
86
BaseDjangoObjectActions,
9-
QuerySetIsh,
107
takes_instance_or_queryset,
118
)
129

@@ -66,42 +63,6 @@ def test_get_djoa_button_attrs_custom_attrs_get_partitioned(self):
6663
self.assertEqual(custom['nonstandard'], 'wombat')
6764

6865

69-
class QuerySetIshTest(TestCase):
70-
fixtures = ['sample_data']
71-
72-
def setUp(self):
73-
# WISHLIST don't depend on fixture
74-
self.obj = Poll.objects.get(pk=1)
75-
76-
def test_can_turn_object_into_queryset(self):
77-
qs = QuerySetIsh(self.obj)
78-
self.assertEqual(qs.count(), 1)
79-
self.assertEqual(qs.get(), self.obj)
80-
self.assertEqual(qs.order_by('foo').get(), self.obj)
81-
self.assertEqual(qs.all().get(), self.obj)
82-
self.assertEqual(qs.filter().get(), self.obj)
83-
self.assertEqual(qs.latest('bar'), self.obj)
84-
85-
def test_queryset_supports_delete(self):
86-
qs = QuerySetIsh(self.obj)
87-
qs.delete()
88-
with self.assertRaises(Poll.DoesNotExist):
89-
Poll.objects.get(pk=1)
90-
91-
@expectedFailure
92-
def test_queryset_supports_filter(self):
93-
# yeah, we don't actually support doing this, but it would be nice.
94-
qs = QuerySetIsh(self.obj)
95-
with self.assertRaises(Poll.DoesNotExist):
96-
# this should be empty because the question is just `"hi"`
97-
qs.filter(question='abra cadabra').get()
98-
99-
def test_queryset_supports_update(self):
100-
qs = QuerySetIsh(self.obj)
101-
qs.update(question='mooo')
102-
self.assertEqual(Poll.objects.get(pk=1).question, 'mooo')
103-
104-
10566
class DecoratorTest(TestCase):
10667
fixtures = ['sample_data']
10768

@@ -128,17 +89,14 @@ def myfunc(foo, bar, queryset):
12889

12990
# passing in an instance yields a queryset (using positional args)
13091
queryset = myfunc(None, None, self.obj)
131-
self.assertIsInstance(queryset, QuerySet)
13292
# the resulting queryset only has one item and it's self.obj
13393
self.assertEqual(queryset.get(), self.obj)
13494

13595
# passing in a queryset yields the same queryset
13696
queryset = myfunc(None, None, self.queryset)
137-
self.assertIsInstance(queryset, QuerySet)
13897
self.assertEqual(queryset, self.queryset)
13998

14099
# passing in an instance yields a queryset (using keyword args)
141100
queryset = myfunc(None, None, queryset=self.obj)
142-
self.assertIsInstance(queryset, QuerySet)
143101
# the resulting queryset only has one item and it's self.obj
144102
self.assertEqual(queryset.get(), self.obj)

django_object_actions/utils.py

Lines changed: 11 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -136,43 +136,23 @@ def message_user(self, request, message):
136136
messages.info(request, message)
137137

138138

139-
class QuerySetIsh(QuerySet):
140-
"""
141-
Takes an instance and mimics it coming from a QuerySet.
142-
143-
This is a hack to support the `takes_instance_or_queryset` decorator so
144-
that you can re-use functions written for standard Django admin actions and
145-
use them for Object Tools too.
146-
"""
147-
def __init__(self, instance=None, *args, **kwargs):
148-
try:
149-
model = instance._meta.model
150-
except AttributeError:
151-
# Django 1.5 does this instead, getting the model may be overkill
152-
# we may be able to throw away all this logic
153-
model = instance._meta.concrete_model
154-
self._doa_instance = instance
155-
super(QuerySetIsh, self).__init__(model, *args, **kwargs)
156-
self._result_cache = [instance]
157-
158-
def _clone(self, *args, **kwargs):
159-
# don't clone me, bro
160-
return self
161-
162-
def get(self, *args, **kwargs):
163-
# Starting in Django 1.7, `QuerySet.get` started slicing to
164-
# `MAX_GET_RESULTS`, so to avoid messing with `__getslice__`, override
165-
# `.get`.
166-
return self._doa_instance
167-
168-
169139
def takes_instance_or_queryset(func):
170140
"""Decorator that makes standard Django admin actions compatible."""
171141
@wraps(func)
172142
def decorated_function(self, request, queryset):
173143
# func follows the prototype documented at:
174144
# https://docs.djangoproject.com/en/dev/ref/contrib/admin/actions/#writing-action-functions
175145
if not isinstance(queryset, QuerySet):
176-
queryset = QuerySetIsh(queryset)
146+
try:
147+
# Django >=1.8
148+
queryset = self.get_queryset(request).filter(pk=queryset.pk)
149+
except AttributeError:
150+
try:
151+
# Django >=1.6,<1.8
152+
model = queryset._meta.model
153+
except AttributeError:
154+
# Django <1.6
155+
model = queryset._meta.concrete_model
156+
queryset = model.objects.filter(pk=queryset.pk)
177157
return func(self, request, queryset)
178158
return decorated_function

example_project/polls/fixtures/sample_data.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@
77
"question": "Do you like me?"
88
}
99
},
10+
{
11+
"pk": 2,
12+
"model": "polls.poll",
13+
"fields": {
14+
"pub_date": "2012-10-20T18:20:38",
15+
"question": "Do you wanna build a snow man?"
16+
}
17+
},
1018
{
1119
"pk": 1,
1220
"model": "polls.choice",

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Django==1.8.4
22
dj-database-url==0.3.0
3-
django-extensions==1.5.5
3+
django-extensions==1.5.9
44
tox==2.1.1
55
factory-boy==2.5.2
66
coverage==3.7.1

tox.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ commands =
1717
{envpython} example_project/manage.py test django_object_actions
1818
deps =
1919
dj_database_url==0.3.0
20-
django-extensions==1.4.6
20+
django-extensions==1.5.9
2121
factory-boy==2.4.1
2222
coveralls: coverage
2323
django14: Django<1.5

0 commit comments

Comments
 (0)