Ik gebruik het Django REST-framework en heb geprobeerd een weergave te maken die een klein beetje informatie retourneert, en deze ook op mijn router te registreren.
Ik heb vier modellen die informatie opslaan, en ze hebben allemaal een veld created_time
. Ik probeer een weergave te maken die de meest recente objecten retourneert (gebaseerd op de created_time
) in een enkele weergave, waarbij alleen de vier aanmaaktijden worden geretourneerd.
Dus, een mogelijke JSON-uitvoer van de weergave zou er als volgt uitzien
{
"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"
}
Ik hoop deze weergave ook op mijn router te registreren, zodat deze bij de rest van mijn eindpunten verschijnt wanneer de API-root wordt geladen.
router.register(r'updatetime', views.UpdateTimeView)
Hier zijn de vier modellen waarmee ik probeer te werken
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)
Is het mogelijk om dit te doen? En hoe zou het gedaan worden?
Antwoord 1, autoriteit 100%
Routers werken met een ViewSet
en zijn niet ontworpen voor normale weergaven, maar dat betekent niet dat u ze niet kunt gebruiken met een normale weergave. Normaal gesproken worden ze gebruikt met modellen (en een ModelViewSet
), maar ze kunnen ook zonder worden gebruikt met behulp van de GenericViewSet
(als u normaal gesproken een GenericAPIView
) en ViewSet
(als je gewoon een APIView
zou gebruiken).
Voor een lijstweergave worden de aanvraagmethoden toegewezen aan ViewSet
methoden zoals deze
get
->list(self, request, format=None)
POST
– >create(self, request, format=None)
Voor detailweergaven (met een primaire sleutel in de url), gebruiken de aanvraagmethoden de volgende kaart
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)
Dus als je een van deze verzoekmethoden wilt gebruiken met je weergave op je router, moet je de juiste weergavemethode overschrijven (dus list()
in plaats van get()
).
Nu, specifiek in jouw geval zou je normaal gesproken een APIView
hebben gebruikt die eruitzag als
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,
})
De vergelijkbare ViewSet
zou zijn
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,
})
Let op de twee vereiste wijzigingen: APIView
-> ViewSet
en get
-> list
. Ik heb ook de naam bijgewerkt om aan te geven dat het meer was dan alleen een normale weergave (aangezien een ViewSet
niet op dezelfde manier kan worden geïnitialiseerd), maar dat is niet vereist.
Dus met deze nieuwe weergave kunt u deze op dezelfde manier als elke andere in de router registreren. Je hebt hier een base_name
nodig zodat de url-namen kunnen worden gegenereerd (normaal gesproken zou dit uit de queryset worden gehaald).
router.register(r'updatetime', views.UpdateTimeViewSet, base_name='updatetime')
Dus nu wordt het updatetime
-eindpunt beschikbaar gemaakt in de API-root en kunt u de laatste tijden krijgen door het eindpunt aan te roepen (een eenvoudig GET-verzoek).
Antwoord 2, autoriteit 4%
Er is nog een manier om het te doen:
urlpatterns = [
# ...
url(r'^you_path/', include(router.urls)),
url(r'^you_path/you_sub_path', views.UpdateTimeView.as_view()),
# ...
]
Maar dingen als Swagger werken daar niet mee