django-rest-framework:如何表示多对多关系?

时间:2017-01-17 16:13:16

标签: python django-rest-framework many-to-many

我正在使用rest api构建一个django应用程序,用户可以在其中订阅供稿。

我的模型看起来像这样:

class Profile(models.Model):
    user = models.OneToOneField(
        User, # standard django user
        on_delete=models.CASCADE,
        primary_key=True
    )

    subscriptions = models.ManyToManyField(Feed, related_name="subscribers")

class Feed(models.Model):
    # These feeds are read-only for the subscribers
    pass

用英语解释:

  

每个用户都有个人资料。这些个人资料可以订阅Feed。该   订阅源只能订阅,不能创建或更新   用户。

我想公开一个休息端点来为当前用户创建,读取,更新和删除订阅。当然,我喜欢使用通用视图,ListCreateAPIViewRetrieveUpdateDeleteAPIView,但我无法弄清楚如何制作正确的序列化器和查询集以使其易于使用。< / p>

我最终/me/subscriptions/直接返回了Feed列表,但POST很奇怪,因为它会创建Feed而不是创建订阅。

我很困惑......任何提示都很受欢迎!

1 个答案:

答案 0 :(得分:2)

您可以使用ModelViewSet并覆盖create方法:

views.py:

from rest_framework import status
from rest_framework import viewsets


class FeedViewSet(serializers.ModelViewSet):  

    serializer_class = FeedSerializer

    def get_queryset(self):
        # show an only related Feed objects to a request.user
        profile = request.user.profile
        return Feed.objects.filter(subscribers=profile)

    def create(self, request, *args, **kwargs):
        pk = request.data.get('pk')
        profile = request.user.profile
        feed = Feed.objects.get(pk=pk)
        profile.subscriptions.add(feed)
        return Response('subscription feed updated!', status=status.HTTP_201_CREATED) 

    # list will work by default
    # other methods like update, delete, retrieve 
    # you could set with NOT_IMPLEMENTED status
    def update(self, request, *args, **kwargs):
        return Response(status=status.HTTP_501_NOT_IMPLEMENTED)

urls.py:

from rest_framework import routers

router = routers.SimpleRouter()
router.register('subscriptions', FeedViewSet, base_name='subscription')

现在,您将拥有一个端点,用于根据Profile更新request.user的订阅。 GET/subscriptions/会显示Feed过滤的所有request.user个对象,POST数据{'pk': <Feed_pk>}/subscriptions/会创建一个链接在FeedProfile之间。