2017-01-17 4 views
1

Ich baue eine Django-Anwendung mit einer Rest-API, in der Benutzer Feeds abonnieren können.django-rest-framework: Wie repräsentiert man eine Viele-zu-Viele-Beziehung?

Mein Modell sieht wie folgt aus:

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 

auf Englisch Erklärt:

Jeder Benutzer ein Profil hat. Dieses Profil kann Feeds abonnieren. Die Feeds können nur abonniert werden, sie können nicht von Benutzern erstellt oder aktualisiert werden.

Ich möchte einen Ruhe-Endpunkt zum Erstellen, Lesen, Aktualisieren und Löschen von Abonnements für den aktuellen Benutzer verfügbar machen. Natürlich würde ich gerne die generischen Ansichten verwenden, eine ListCreateAPIView und eine RetrieveUpdateDeleteAPIView, aber ich kann nicht herausfinden, wie man die richtigen Serialisierer und Abfragesätze erstellt, um diese einfach zu verwenden.

Ich endete mit /me/subscriptions/ eine Liste der Feeds direkt zurück, aber dann ist die POST seltsam, weil es einen Feed erstellen würde, anstatt ein Abonnement zu erstellen.

Ich bin verwirrt ... Jeder Hinweis ist willkommen!

+0

Benutzerprofil basierend auf 'request.user'? zum Beispiel 'GET''/subscriptions/'sollte Abonnements' Feed' für diesen Benutzer zurückgeben und 'POST' sollte einen mtm Link zu diesem Benutzer erstellen? –

Antwort

2

könnten Sie einen ModelViewSet verwenden und außer Kraft setzen create Methode:

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') 

Jetzt müssen Sie einen Endpunkt haben Abonnements für die Aktualisierung von Profile basierend auf einem request.user. GET-/subscriptions/ zeigt alle Feed Objekte gefiltert nach request.user und POST mit Daten {'pk': <Feed_pk>}-/subscriptions/ wird eine Verbindung zwischen Feed und Profile erstellen.

+0

Das klingt nach einer vernünftigen Lösung. Aber ich frage mich, ob es nicht einfacher/weniger Code wäre, wenn ich ein Durchgangsobjekt in meiner Viele-zu-Viele-Beziehung definieren würde, und dann, falls überhaupt möglich, entlarven würde. – aspyct

+0

@aspyct gibt es keinen Unterschied, mit through müssen Sie immer noch eine 'create' Methode überschreiben, weil Ihr Zweck ist, Link zu erstellen, anstatt Objekt zu erstellen –

Verwandte Themen