Skip to content

Commit

Permalink
Invalidate any existing prefetch cache on PUT requests. (encode#4668)
Browse files Browse the repository at this point in the history
  • Loading branch information
tomchristie authored Nov 11, 2016
1 parent 8bab7f8 commit 24791cb
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 5 deletions.
11 changes: 10 additions & 1 deletion docs/api-guide/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,12 @@ As usual CSRF validation will only apply to any session authenticated views. Th
# RequestsClient

REST framework also includes a client for interacting with your application
using the popular Python library, `requests`.
using the popular Python library, `requests`. This may be useful if:

* You are expecting to interface with the API primarily from another Python service,
and want to test the service at the same level as the client will see.
* You want to write tests in such a way that they can also be run against a staging or
live environment. (See "Live tests" below.)

This exposes exactly the same interface as if you were using a requests session
directly.
Expand All @@ -198,6 +203,10 @@ directly.

Note that the requests client requires you to pass fully qualified URLs.

## `RequestsClient` and working with the database

The `RequestsClient` class is useful if

## Headers & Authentication

Custom headers and authentication credentials can be provided in the same way
Expand Down
5 changes: 2 additions & 3 deletions rest_framework/mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,8 @@ def update(self, request, *args, **kwargs):

if getattr(instance, '_prefetched_objects_cache', None):
# If 'prefetch_related' has been applied to a queryset, we need to
# refresh the instance from the database.
instance = self.get_object()
serializer = self.get_serializer(instance)
# forcibly invalidate the prefetch cache on the instance.
instance._prefetched_objects_cache = {}

return Response(serializer.data)

Expand Down
20 changes: 19 additions & 1 deletion tests/test_prefetch_related.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class Meta:


class UserUpdate(generics.UpdateAPIView):
queryset = User.objects.all().prefetch_related('groups')
queryset = User.objects.exclude(username='exclude').prefetch_related('groups')
serializer_class = UserSerializer


Expand All @@ -39,3 +39,21 @@ def test_prefetch_related_updates(self):
'email': '[email protected]'
}
assert response.data == expected

def test_prefetch_related_excluding_instance_from_original_queryset(self):
"""
Regression test for https://github.com/tomchristie/django-rest-framework/issues/4661
"""
view = UserUpdate.as_view()
pk = self.user.pk
groups_pk = self.groups[0].pk
request = factory.put('/', {'username': 'exclude', 'groups': [groups_pk]}, format='json')
response = view(request, pk=pk)
assert User.objects.get(pk=pk).groups.count() == 1
expected = {
'id': pk,
'username': 'exclude',
'groups': [1],
'email': '[email protected]'
}
assert response.data == expected

0 comments on commit 24791cb

Please sign in to comment.