Fix UpdateModelMixin to work when no queryset is defined

Fix #9306
This commit is contained in:
Bruno Alla 2024-03-19 21:44:00 +00:00
parent 77ef27f18f
commit 89c79d6649
No known key found for this signature in database
2 changed files with 21 additions and 5 deletions

View File

@ -69,13 +69,14 @@ class UpdateModelMixin:
serializer.is_valid(raise_exception=True)
self.perform_update(serializer)
queryset = self.filter_queryset(self.get_queryset())
if queryset._prefetch_related_lookups:
if hasattr(instance, '_prefetched_objects_cache'):
# If 'prefetch_related' has been applied to a queryset, we need to
# forcibly invalidate the prefetch cache on the instance,
# and then re-prefetch related objects
# forcibly invalidate the prefetch cache on the instance
instance._prefetched_objects_cache = {}
prefetch_related_objects([instance], *queryset._prefetch_related_lookups)
queryset = self.filter_queryset(self.get_queryset())
if getattr(queryset, '_prefetch_related_lookups', None):
# And then re-prefetch related objects
prefetch_related_objects([instance], *queryset._prefetch_related_lookups)
return Response(serializer.data)

View File

@ -35,6 +35,13 @@ class UserUpdateWithoutPrefetchRelated(generics.UpdateAPIView):
serializer_class = UserSerializer
class UserRetrieveWithoutQuerySet(generics.RetrieveUpdateAPIView):
serializer_class = UserSerializer
def get_object(self):
return User.objects.get(pk=self.kwargs['pk'])
class TestPrefetchRelatedUpdates(TestCase):
def setUp(self):
self.user = User.objects.create(username='tom', email='tom@example.com')
@ -90,3 +97,11 @@ class TestPrefetchRelatedUpdates(TestCase):
)
with self.assertNumQueries(16):
UserUpdateWithoutPrefetchRelated.as_view()(request, pk=self.user.pk)
def test_can_update_without_queryset(self):
request = factory.patch('/', {'username': 'new'})
response = UserRetrieveWithoutQuerySet.as_view()(request, pk=self.user.pk)
assert response.data['id'] == self.user.id
assert response.data['username'] == 'new'
self.user.refresh_from_db()
assert self.user.username == 'new'