I am using Django REST framework and have been trying to create a view that returns a small bit of information, as well as register it on my router.
I have four models which store information, and all of them have a created_time
field. I am trying to make a view that returns the most recent objects (based on the created_time
) in a single view, where only the four creation times are returned.
So, a possible JSON output from the view would look like
{
"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"
}
I am also hoping to register this view on my router, so it appears with the rest of my endpoints when the API root is loaded.
router.register(r'updatetime', views.UpdateTimeView)
Here are the four models that I am trying to work with
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 it possible to do this? And how would it be done?
Routers work with a
ViewSet
and aren't designed for normal views, but that doesn't mean that you cannot use them with a normal view. Normally they are used with models (and aModelViewSet
), but they can be used without them using theGenericViewSet
(if you would normally use aGenericAPIView
) andViewSet
(if you would just use anAPIView
).For a list view, the request methods are mapped to
ViewSet
methods like thisGET
->list(self, request, format=None)
POST
- >create(self, request, format=None)
For detail views (with a primary key in the url), the request methods use the following map
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)
So if you want to use any of these request methods with your view on your router, you need to override the correct view method (so
list()
instead ofget()
).Now, specifically in your case you would have normally use an
APIView
that looked likeThe comparable
ViewSet
would beNotice the two required changes:
APIView
->ViewSet
andget
->list
. I also updated the name to indicate that it was more than just a normal view (as aViewSet
cannot be initialized the same way), but that's not required.So with this new view, you can just register it in the router the same way as any other. You need a
base_name
here so the url names can be generated (normally this would pull from the queryset).So now the
updatetime
endpoint will be made available in the API root and you can get the latest times by just calling the endpoint (a simple GET request).There is one more way to do it:
But stuff like Swagger will not work with that