wake-up-neo.com

Wie kann ich eine einzelne Ansicht (keine Ansichten) auf meinem Router registrieren?

Ich verwende das Django REST - Framework und habe versucht, eine Ansicht zu erstellen, die ein wenig Information zurückgibt, und sie auf meinem Router zu registrieren.

Ich habe vier Modelle, die Informationen speichern, und alle haben ein created_time-Feld. Ich versuche, eine Ansicht zu erstellen, die die neuesten Objekte (basierend auf created_time) in einer einzigen Ansicht zurückgibt, wobei nur die vier Erstellungszeiten zurückgegeben werden.

Eine mögliche JSON-Ausgabe aus der Sicht würde also aussehen

{
    "publish_updatetime": "2015.05.20 11:53",
    "meeting_updatetime": "2015.05.20 11:32",
    "training_updatetime": "2015.05.20 15:25",
    "exhibiting_updatetime": "2015.05.19 16:23"
}

Ich hoffe auch, diese Ansicht auf meinem Router zu registrieren, so dass sie mit den restlichen Endpunkten angezeigt wird, wenn das API-Stammverzeichnis geladen wird.

router.register(r'updatetime', views.UpdateTimeView)

Hier sind die vier Modelle, mit denen ich versuche zu arbeiten

class Publish(models.Model):
    user = models.ForeignKey(MyUser)
    name = models.CharField(max_length=50)
    created_time = models.DateTimeField( default=datetime.now)

class Meeting(models.Model):
    user = models.ForeignKey(MyUser)
    name = models.CharField(max_length=50)
    file_addr = models.FileField(upload_to=get_file_path)
    created_time = models.DateTimeField(default=datetime.now)

class Training(models.Model):
    user = models.ForeignKey(MyUser)
    name = models.CharField(max_length=50)
    image = models.ImageField(upload_to=get_file_path, max_length=255)
    created_time = models.DateTimeField(default=datetime.now)

class Exhibiting(models.Model):
    user = models.ForeignKey(MyUser)
    name = models.CharField(max_length=50)
    file_addr = models.FileField(upload_to=get_file_path)
    created_time = models.DateTimeField(default=datetime.now)

Kann man das machen? Und wie würde es gemacht werden?

44
flytofuture

Router funktionieren mit einem ViewSet und sind nicht für normale Ansichten konzipiert, was jedoch nicht bedeutet, dass sie nicht mit einer normalen Ansicht verwendet werden können. Normalerweise werden sie mit Modellen (und einem ModelViewSet) verwendet, sie können jedoch ohne sie mit GenericViewSet (wenn Sie normalerweise ein GenericAPIView verwenden) und ViewSet (wenn Sie nur ein APIView verwenden würden) verwendet werden.

Für eine Listenansicht werden die Anforderungsmethoden ViewSet-Methoden wie folgt zugeordnet

  • GET -> list(self, request, format=None)
  • POST-> create(self, request, format=None)

Für Detailansichten (mit einem Primärschlüssel in der URL) verwenden die Anforderungsmethoden die folgende Zuordnung

  • GET -> retrieve(self, request, pk, format=None)
  • PUT -> update(self, request, pk, format=None)
  • PATCH -> partial_update(self, request, pk, format=None)
  • DELETE -> destroy(self, request, pk, format=None)

Wenn Sie also eine dieser Anforderungsmethoden mit Ihrer Ansicht auf Ihrem Router verwenden möchten, müssen Sie die korrekte Ansichtsmethode überschreiben (also list() anstelle von get()).


Nun, speziell in Ihrem Fall hätten Sie normalerweise ein APIView verwendet, das aussah

class UpdateTimeView(APIView):

    def get(self, request, format=None):
        latest_publish = Publish.objects.latest('created_time')
        latest_meeting = Meeting.objects.latest('created_time')
        latest_training = Training.objects.latest('created_time')
        latest_exhibiting = Exhibiting.objects.latest('created_time')

        return Response({
            "publish_updatetime": latest_publish.created_time,
            "meeting_updatetime": latest_meeting.created_time,
            "training_updatetime": latest_training.created_time,
            "exhibiting_updatetime": latest_exhibiting.created_time,
        })

Das vergleichbare ViewSet wäre

class UpdateTimeViewSet(ViewSet):

    def list(self, request, format=None):
        latest_publish = Publish.objects.latest('created_time')
        latest_meeting = Meeting.objects.latest('created_time')
        latest_training = Training.objects.latest('created_time')
        latest_exhibiting = Exhibiting.objects.latest('created_time')

        return Response({
            "publish_updatetime": latest_publish.created_time,
            "meeting_updatetime": latest_meeting.created_time,
            "training_updatetime": latest_training.created_time,
            "exhibiting_updatetime": latest_exhibiting.created_time,
        })

Beachten Sie die zwei erforderlichen Änderungen: APIView -> ViewSet und get -> list. Ich habe auch den Namen aktualisiert, um anzuzeigen, dass es mehr als nur eine normale Ansicht war (da ViewSet nicht auf dieselbe Weise initialisiert werden kann). Dies ist jedoch nicht erforderlich.

Mit dieser neuen Ansicht können Sie sie genauso wie jede andere im Router registrieren. Sie benötigen hier einen base_name, damit die URL-Namen generiert werden können (normalerweise würde dies aus dem Abfrageset stammen).

router.register(r'updatetime', views.UpdateTimeViewSet, base_name='updatetime')

Nun wird der updatetime-Endpunkt im API-Stamm verfügbar gemacht, und Sie können die neuesten Zeiten abrufen, indem Sie einfach den Endpunkt (eine einfache GET-Anforderung) aufrufen.

56
Kevin Brown

Es gibt eine weitere Möglichkeit, dies zu tun:

urlpatterns = [
    # ... 
    url(r'^you_path/', include(router.urls)),
    url(r'^you_path/you_sub_path', views.UpdateTimeView.as_view()),
    # ... 
]

Aber Sachen wie Swagger werden damit nicht funktionieren

0
Alexander