Django REST framework queryset object has no attribute pk

Question:

I am building a larger Django-based web app, but I have a blocking issue with an API view that should return some data.

I the application I have a model (mail.models.Message) and a matching serializer and viewset.

For a reporting feature, I need to get filtered set of results and have therefoer created a seperate rest_framework.views.APIView for the purpose of the reporting. The model is located in one app and the reporting is in another app.

Here is the model:

class Message(models.Model):
class Meta:
    ordering = ('-timestamp',)
    get_latest_by = 'timestamp'

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    from_address = models.CharField("From", max_length=511, blank=True, default="", db_index=True)
    from_domain = models.CharField(max_length=255, blank=True, default="", db_index=True)
    to_address = models.CharField("To", max_length=511, blank=True, default="", db_index=True)
    to_domain = models.CharField(max_length=255, blank=True, default="", db_index=True)
    subject = models.TextField(blank=True, default="", db_index=True)
    client_ip = models.GenericIPAddressField("Client IP", db_index=True, null=True)
    mailscanner_hostname = models.CharField(max_length=255, db_index=True)
    spam_score = models.DecimalField(db_index=True, default=0.00, max_digits=7, decimal_places=2)
    mcp_score = models.DecimalField(db_index=True, default=0.00, max_digits=7, decimal_places=2)
    timestamp = models.DateTimeField(db_index=True)
    size = models.FloatField(default=0)
    token = models.CharField(max_length=255, null=True)
    mailq_id = models.TextField("Mailqueue identification", null=True)
    whitelisted = models.BooleanField(db_index=True, default=False)
    blacklisted = models.BooleanField(db_index=True, default=False)
    is_spam = models.BooleanField(db_index=True, default=False)
    is_mcp = models.BooleanField(db_index=True, default=False)
    is_rbl_listed = models.BooleanField("Is RBL listed", db_index=True, default=False)
    quarantined = models.BooleanField(db_index=True, default=False)
    infected = models.BooleanField(db_index=True, default=False)
    released = models.BooleanField(db_index=True, default=False)

    def __str__(self):
        return str(self.id) + "[" + str(self.from_address) + " to " + str(self.to_address) + "]"

And the matching serializer:

class MessageSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Message
        fields = (
            'id',
            'url',
            'from_address',
            'from_domain',
            'to_address',
            'to_domain',
            'subject',
            'client_ip',
            'mailscanner_hostname',
            'spam_score',
            'timestamp',
            'size',
            'token',
            'whitelisted',
            'blacklisted',
            'is_spam',
            'is_rbl_listed',
            'quarantined',
            'infected'
        )

The model has a lot of indexes on it to improve the performance search and filtering, but I have excluded these.

For the reporting, I have created this special view:

class MessageListApiView(ReportApiView):
    serializer_class = MessageSerializer
    queryset = Message.objects.all()

    def get_queryset(self):
        if self.request.method == 'POST':
            filters = self.request.data
            return MessageQuerySetFilter.filter(MessageQuerySetFilter, self.queryset, filters)
        else:
            return self.queryset


    def post(self, request, format=None):
        filters = request.data
        qs = self.get_queryset()
        serializer = MessageSerializer(qs, context={'request': request})
        return Response(serializer.data, 200)

In get_queryset, I use a special class and the only purpose of that class is to apply the appropriate filtering on the queryset and return it. Doing some testing, I have found the issue occurs when I have to return the Response.

I get this traceback:

Internal Server Error: /api/reports/messages/
Traceback (most recent call last):
  File "/Users/kenneth/Code/mailware/lib/python3.6/site-packages/django/core/handlers/exception.py", line 35, in inner
response = get_response(request)
  File "/Users/kenneth/Code/mailware/lib/python3.6/site-packages/django/core/handlers/base.py", line 128, in _get_response
response = self.process_exception_by_middleware(e, request)
      File "/Users/kenneth/Code/mailware/lib/python3.6/site-packages/django/core/handlers/base.py", line 126, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/Users/kenneth/Code/mailware/lib/python3.6/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
  File "/Users/kenneth/Code/mailware/lib/python3.6/site-packages/django/views/generic/base.py", line 69, in view
return self.dispatch(request, *args, **kwargs)
  File "/Users/kenneth/Code/mailware/lib/python3.6/site-packages/rest_framework/views.py", line 494, in dispatch
response = self.handle_exception(exc)
  File "/Users/kenneth/Code/mailware/lib/python3.6/site-packages/rest_framework/views.py", line 454, in handle_exception
self.raise_uncaught_exception(exc)
  File "/Users/kenneth/Code/mailware/lib/python3.6/site-packages/rest_framework/views.py", line 491, in dispatch
response = handler(request, *args, **kwargs)
  File "/Users/kenneth/Code/mailware/src/reports/views.py", line 44, in post
return Response(serializer.data, 200)
  File "/Users/kenneth/Code/mailware/lib/python3.6/site-packages/rest_framework/serializers.py", line 537, in data
ret = super(Serializer, self).data
  File "/Users/kenneth/Code/mailware/lib/python3.6/site-packages/rest_framework/serializers.py", line 262, in data
self._data = self.to_representation(self.instance)
  File "/Users/kenneth/Code/mailware/lib/python3.6/site-packages/rest_framework/serializers.py", line 504, in to_representation
ret[field.field_name] = field.to_representation(attribute)
  File "/Users/kenneth/Code/mailware/lib/python3.6/site-packages/rest_framework/relations.py", line 376, in to_representation
url = self.get_url(value, self.view_name, request, format)
  File "/Users/kenneth/Code/mailware/lib/python3.6/site-packages/rest_framework/relations.py", line 312, in get_url
lookup_value = getattr(obj, self.lookup_field)
AttributeError: 'QuerySet' object has no attribute 'pk'
[19/Jan/2018 20:05:24] "POST /api/reports/messages/ HTTP/1.1" 500 16389

The above APIView class inherits a custom base class, which is what inherits the rest_framework.views.APIView class. This class is called ReportApiView and simply sets the paginator_class and the permission_class

class ReportApiView(APIView):
    permission_classes = (IsAuthenticated,)
    pagination_class = PageNumberPaginationWithPageCount

In the MessageListApiView post method it seems to go wrong in the return line, but I cannot find the reason why it is not working

Asked By: Kenneth_H

||

Answers:

You need to add many=True to serializer queryset:

serializer = MessageSerializer(qs, many=True, context={'request': request})
Answered By: neverwalkaloner

just you need to add many = true in serializer
serializer = userSerializer.UserSeria(user,data=request.data,many=True)

Answered By: Awais Niaz

I had this error, for the ones coming here from Google, my problem was this one:

The model I wanted to serialize had a field containing unique=True in it. The multiple data I sent to the Serializer (with many=True) were not unique (already in db), and instead of having an error telling me this, the "'QuerySet' object has no attribute 'pk'" was thrown which is really confusing. Anyway, after getting rid of the uniqueness, my code works.

Answered By: Dardan Iljazi
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.