list_route出错:Viewset中的POST方法

时间:2017-12-22 09:09:45

标签: python django django-rest-framework

我正在创建一个功能添加好友哪个用户可以为另一个用户用户URL创建一个友谊请求对象:http://localhost:8000/api/v1/users/{username}/add_friend/但是我在制作时出错。

Urls.py中的代码

from .views import (AddFriendUserAPIView)
urlpatterns = [
    url(r'^(?P<username>[\w-]+)/add_friend/$', AddFriendUserAPIView.as_view({'post': 'add_friend'}), name='add_friend'),
]

Views.py中的代码

class AddFriendUserAPIView(ReadOnlyModelViewSet):
    serializer_class = FriendRequestSerializer
    queryset = FriendshipRequest.objects.all()
    lookup_field = 'username'

    @detail_route(methods=['POST'])
    def add_friend(self, request, username):
        to_user = User.objects.get(username=request.data['to_user_username'])
        add_qs = FriendshipRequest.objects.get_or_create(from_user=request.user, to_user=to_user , message='')
        serializer = FriendRequestSerializer(add_qs)
        return Response(serializer.data)

serializers.py中的代码

class FriendRequestSerializer(ModelSerializer):
    class Meta:
        model = FriendshipRequest
        fields = (
            'id',
            'from_user',
            'to_user',
            'message', 
        )

朋友请求的模型中的代码:

class FriendshipRequest(models.Model):
    from_user = models.ForeignKey(User, related_name='friendship_requests_sent')
    to_user = models.ForeignKey(User, related_name='friendship_requests_received')
    message = models.TextField(blank=True)

Trackback错误日志

    Traceback:

File "C:\Python27\lib\site-packages\django\core\handlers\exception.py" in inner
  41.             response = get_response(request)

File "C:\Python27\lib\site-packages\django\core\handlers\base.py" in _get_response
  187.                 response = self.process_exception_by_middleware(e, request)

File "C:\Python27\lib\site-packages\django\core\handlers\base.py" in _get_response
  185.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "C:\Python27\lib\site-packages\django\views\decorators\csrf.py" in wrapped_view
  58.         return view_func(*args, **kwargs)

File "C:\Python27\lib\site-packages\rest_framework\viewsets.py" in view
  90.             return self.dispatch(request, *args, **kwargs)

File "C:\Python27\lib\site-packages\rest_framework\views.py" in dispatch
  489.             response = self.handle_exception(exc)

File "C:\Python27\lib\site-packages\rest_framework\views.py" in handle_exception
  449.             self.raise_uncaught_exception(exc)

File "C:\Python27\lib\site-packages\rest_framework\views.py" in dispatch
  486.             response = handler(request, *args, **kwargs)

File "C:\Users\User\Desktop\FeedGit\backend\api\authentication\add_friend.py" in add_friend
  16.         to_user = User.objects.get(username=request.data['to_user_username'])

File "C:\Python27\lib\site-packages\django\utils\datastructures.py" in __getitem__
  85.             raise MultiValueDictKeyError(repr(key))

Exception Type: MultiValueDictKeyError at /api/v1/users/duongnuhabang/add_friend/
Exception Value: "'to_user_username'"

2 个答案:

答案 0 :(得分:1)

您的add_friend接受两个参数,即selfrequest。但是,您的URL也传递了关键字参数usernameusername参数不在您的方法的参数中,因此不能作为参数传递。将用户名作为参数添加到add_friend应该可以解决问题。

def add_friend(self, request, username):
     ...

除此之外,您的网址中传递的用户名永远不会在您的add_friend方法中使用。

答案 1 :(得分:1)

又是你了。你必须对DRF有一些误解。 首先,您最好使用路由器来托管您的网址ModelViewSet。例如:

项目/ urls.py

from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r'user', UserViewSet, base_name='user')
urlpatterns = [
    url(r'^', include(router.urls)),
    url(r'^admin/', admin.site.urls),
]

第二个是你所需要的detail_router而不是list_router

views.py

class UserViewSet(ReadOnlyModelViewSet):
    serializer_class = UserSerializer
    queryset = User.objects.all()
    lookup_field = username

    @detail_route(methods=['POST'])
    def add_friend(self, request, username):
        to_user = self.get_object()
        add_qs = FriendshipRequest.objects.get_or_create(from_user=request.user, to_user=to_user , message='')
        serializer = FriendRequestSerializer(add_qs)
        return Response(serializer.data)

将数据{}发布到www.example.com/user/【to_user_username】/add_friend/

如果你真的想在FriendShipViewSet中做这个(你可能更喜欢这种风格),这里是demo:

from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r'friendship', FriendShipViewSet, base_name='friendship')
urlpatterns = [
    url(r'^', include(router.urls)),
    url(r'^admin/', admin.site.urls),
]


class FriendShipViewSet(ReadOnlyModelViewSet):
    serializer_class = FriendShipRequestSerializer
    queryset = FriendShip.objects.all()

    @list_route(methods=['POST'])
    def add_friend(self, request):
        to_user = User.objects.get(username=request.data['to_user_username'])
        add_qs = FriendshipRequest.objects.get_or_create(from_user=request.user, to_user=to_user , message='')
        serializer = self.get_serializer(add_qs)
        return Response(serializer.data)

将数据{'to_user_username': 'your_custom_to_user_username'}发布到www.example.com/friendship/add_friend/