Skip to content

Commit 80e09d0

Browse files
committed
Fix UpdateModelMixin to work when no queryset is defined
Fix #9306
1 parent 77ef27f commit 80e09d0

File tree

2 files changed

+22
-6
lines changed

2 files changed

+22
-6
lines changed

rest_framework/mixins.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
We don't bind behaviour to http method handlers yet,
55
which allows mixin classes to be composed in interesting ways.
66
"""
7-
from django.db.models.query import prefetch_related_objects
7+
from django.db.models.query import prefetch_related_objects, QuerySet
88

99
from rest_framework import status
1010
from rest_framework.response import Response
@@ -69,13 +69,14 @@ def update(self, request, *args, **kwargs):
6969
serializer.is_valid(raise_exception=True)
7070
self.perform_update(serializer)
7171

72-
queryset = self.filter_queryset(self.get_queryset())
73-
if queryset._prefetch_related_lookups:
72+
if hasattr(instance, '_prefetched_objects_cache'):
7473
# If 'prefetch_related' has been applied to a queryset, we need to
75-
# forcibly invalidate the prefetch cache on the instance,
76-
# and then re-prefetch related objects
74+
# forcibly invalidate the prefetch cache on the instance
7775
instance._prefetched_objects_cache = {}
78-
prefetch_related_objects([instance], *queryset._prefetch_related_lookups)
76+
queryset = self.filter_queryset(self.get_queryset())
77+
if getattr(queryset, '_prefetch_related_lookups', None):
78+
# And then re-prefetch related objects
79+
prefetch_related_objects([instance], *queryset._prefetch_related_lookups)
7980

8081
return Response(serializer.data)
8182

tests/test_prefetch_related.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,13 @@ class UserUpdateWithoutPrefetchRelated(generics.UpdateAPIView):
3535
serializer_class = UserSerializer
3636

3737

38+
class UserRetrieveWithoutQuerySet(generics.RetrieveUpdateAPIView):
39+
serializer_class = UserSerializer
40+
41+
def get_object(self):
42+
return User.objects.get(pk=self.kwargs['pk'])
43+
44+
3845
class TestPrefetchRelatedUpdates(TestCase):
3946
def setUp(self):
4047
self.user = User.objects.create(username='tom', email='[email protected]')
@@ -90,3 +97,11 @@ def test_db_query_count(self):
9097
)
9198
with self.assertNumQueries(16):
9299
UserUpdateWithoutPrefetchRelated.as_view()(request, pk=self.user.pk)
100+
101+
def test_can_update_without_queryset(self):
102+
request = factory.patch('/', {'username': 'new'})
103+
response = UserRetrieveWithoutQuerySet.as_view()(request, pk=self.user.pk)
104+
assert response.data['id'] == self.user.id
105+
assert response.data['username'] == 'new'
106+
self.user.refresh_from_db()
107+
assert self.user.username == 'new'

0 commit comments

Comments
 (0)