【发布时间】:2023-03-09 10:30:01
【问题描述】:
我必须为现有的基于 Django 的网络应用程序创建一个 API,并且我正在使用 DRF 来执行此操作。虽然我以前从未使用过 DRF,但在我遇到这个问题之前,一切都非常清晰和良好。这是有问题的网址:
http://www.<customer-website-name>.com/api/friendship-requests/<sender-pk>/
根据给我的需求规范,应该这样处理:
- [GET] 返回一个
FriendshipRequest对象,该对象由其pk = <sender-pk>的用户发送给当前经过身份验证的用户,如果此类请求不存在,则返回404。 - [PUT] 接受
AcceptReject对象(例如,JSON{"accepted": false})。如果accepted == True,清理FriendshipRequest,新建Friendship对象,返回201;如果accepted == False,将FriendshipRequest标记为拒绝,返回204
这是AcceptReject 类,它是序列化程序:
class AcceptReject(object):
def __init__(self, accepted):
self.accepted = accepted
class AcceptRejectSerializer(serializers.Serializer):
accepted = serializers.BooleanField()
这是我用来处理 url 的视图:
class FriendshipRequestDetail(mixins.RetrieveModelMixin,
generics.GenericAPIView):
def get_serializer_class(self):
if self.request.method == 'PUT':
return serializers.AcceptRejectSerializer
return serializers.FriendshipRequestSerializer
def get_object(self):
sender = generics.get_object_or_404(get_user_model(),
pk=self.kwargs['pk'])
obj = generics.get_object_or_404(FriendshipRequest,
from_user=sender,
to_user=self.request.user)
self.check_object_permissions(self.request, obj)
return obj
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
def put(self, request, *args, **kwargs):
return Response(status=status.HTTP_204_NO_CONTENT)
我天真地认为重写 get_serializer_class() 以根据请求方法返回序列化程序就足够了,但事实并非如此。
另外,如您所见,我什至还没有开始编写 PUT 处理程序。当我尝试使用可浏览的 api 时,它的存在就足以导致以下错误:
Environment:
Request Method: GET
Request URL: http://127.0.0.1:8000/api/friendship-requests/5/
Django Version: 1.8.4
Python Version: 3.4.3
Installed Applications:
('django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.gis',
'rest_framework',
'rest_framework.authtoken',
'friendship',
'REDACTED.REDACTED')
Installed Middleware:
('django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware')
Traceback:
File "/home/manvis/REDACTED/env/lib/python3.4/site-packages/django/core/handlers/base.py" in get_response
164. response = response.render()
File "/home/manvis/REDACTED/env/lib/python3.4/site-packages/django/template/response.py" in render
158. self.content = self.rendered_content
File "/home/manvis/REDACTED/env/lib/python3.4/site-packages/rest_framework/response.py" in rendered_content
71. ret = renderer.render(self.data, media_type, context)
File "/home/manvis/REDACTED/env/lib/python3.4/site-packages/rest_framework/renderers.py" in render
669. context = self.get_context(data, accepted_media_type, renderer_context)
File "/home/manvis/REDACTED/env/lib/python3.4/site-packages/rest_framework/renderers.py" in get_context
614. raw_data_put_form = self.get_raw_data_form(data, view, 'PUT', request)
File "/home/manvis/REDACTED/env/lib/python3.4/site-packages/rest_framework/renderers.py" in get_raw_data_form
561. content = renderer.render(serializer.data, accepted, context)
File "/home/manvis/REDACTED/env/lib/python3.4/site-packages/rest_framework/serializers.py" in data
487. ret = super(Serializer, self).data
File "/home/manvis/REDACTED/env/lib/python3.4/site-packages/rest_framework/serializers.py" in data
223. self._data = self.to_representation(self.instance)
File "/home/manvis/REDACTED/env/lib/python3.4/site-packages/rest_framework/serializers.py" in to_representation
447. attribute = field.get_attribute(instance)
File "/home/manvis/REDACTED/env/lib/python3.4/site-packages/rest_framework/fields.py" in get_attribute
418. raise type(exc)(msg)
Exception Type: AttributeError at /api/friendship-requests/5/
Exception Value: Got AttributeError when attempting to get a value for field `accepted` on serializer `AcceptRejectSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `FriendshipRequest` instance.
Original exception text was: 'FriendshipRequest' object has no attribute 'accepted'.
就像我说的,这是我第一次使用 DRF,但是,如果我正确理解了跟踪,似乎错误源于 DRF 试图为可浏览的 api 呈现表单,不幸的是,我不能去没有它,因为可浏览的 api 也是必需的。
我还需要更改/覆盖什么才能使可浏览的 api 用于此视图?
【问题讨论】:
标签: django python-3.x django-rest-framework