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
您需要将many=True
添加到序列化器查询集:
serializer = MessageSerializer(qs, many=True, context={'request': request})
只是你需要在序列化程序中添加 many = true serializer = userSerializer.UserSeria(user,data=request.data,many=True)
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.