0

Simplified model structure (I'm leaving out important bits, obviously, there are good reasons these are in different models):

class Contact(models.Model):
    receive_marketing = models.DateTimeField(null=True, blank=True)

class User(models.Model):
    email_hash = models.CharField(max_length=255)
    contact = models.ForeignKey(Contact)

This stores whether interested people want to receive email offers, etc. We have a page where people can change these settings, which uses the hash to identify the person so people can't change other's settings, see who's signed up, etc. The values are fully alpha-numeric.

The view looks like this:

class ContactViewSet(viewsets.ModelViewSet):
    queryset = Contact.objects.all()
    permission_classes = (AllowAny, )

    def get_queryset(self):
        if self.request.user.is_staff:
            return ContactViewSet.queryset

        token = self.request.query_params.get('ref')
        return Contact.objects.filter(user__email_hash__isnull=False,
                                      user__email_hash=token).distinct()

So staff members can see and access all Contact entries, but otherwise we'll return a queryset with one entry, the Contact linked to a User with an email_hash that matches the ref query param.

This passes all the unittests checking various combinations of staff and not, with and without the ref query param, etc.

If I log into our remote environment and start a django shell, I can do the following:

>>> from user.views import ContactViewSet
>>> from rest_framework.test import APIRequestFactory
>>> factory = APIRequestFactory()
>>> view = ContactViewSet.as_view({'get': 'list'})
>>> request = factory.get('/contact/?ref=a-valid-hash')
>>> view(request).rendered_content
b'{"count":1,"next":null,"previous":null,"results":[{"id":222,"receive_marketing":"2018-05-15T14:11:13.449719Z"}]}'

However, if you then make that exact same request from a browser or curl:

$ curl http://user-service-url/contact/?ref=a-valid-hash
{"count":0,"next":null,"previous":null,"results":[]}

We've disabled all kinds of caching, we're not going through any kind of proxy service, yet we repeatedly, but not consistently, get no results for "proper" requests, when all unittests and manual shell requests return the correct result.

Any suggestions of where to look? What other processing of data doesn't happen when requesting via a test request factory?

cruise
  • 106
  • 4

2 Answers2

0

User authentication seems to be missing in test request factory, so it is fetching without any filter. What value is set for user object in self.request.user

Or it could be ref value is not properly set.

Vinay P
  • 617
  • 3
  • 13
0

Turns out the issue was in the Serializer, which had specified a Policy class. No idea why having a Policy on the Serializer made it sometimes return no results and other times return the correct results, but after spending four days on this I don't care, I'm just glad it works.

cruise
  • 106
  • 4