What are the differences between the APIView and ViewSets classes? I am following Django REST-framework official documentation. I find it lacking in examples.
Can you explain the above difference with a suitable example?
APIView is the most basic class that you usually override when defining your REST view. You usually define your methods like get, put, delete and others see: http://www.cdrf.co/3.5/rest_framework.views/APIView.html. With APIView you define your view and add it to your urls like so:
# in views.py
class MyAPIView(APIView):
... #here you put your logic check methods you can use
# in urls.py
url(r'^posts$', MyAPIView.as_view()), #List of all the posts
Because certain things like getting /post/4, deleting /post/4, getting all posts, updating posts, and creating new posts are so common DRF provides ViewSets.
Before you use ViewSets, let me tell you about Generic Classes. They things very well, but you need to provide the full API end point like I did with my MyAPIView view (again for more info check http://www.cdrf.co/ or http://www.django-rest-framework.org/). So you would have to define your own urls path.
But with ViewSets you create ViewSet that actually merges all the above described operations and also you don't need to define the url path you, instead you use a router that makes paths for you like this:
# views.py
class PostViewSet(ViewSet): # here you subclass ViewSet check methods you can override, you have also ModelViewSet,...
# urls.py
router = routers.DefaultRouter()
router.register(r'post', PostViewSet, base_name='Post')
APIView allow us to define functions that match standard HTTP methods like GET, POST, PUT, PATCH, etc.
Viewsets allow us to define functions that match to common API object actions like : LIST, CREATE, RETRIEVE, UPDATE, etc.
Viewsets are also used to write logic to perform standard database operations and to interface with a database back-end. And are usually used for existing database model to manage predefined objects.
The functions you add to the APIView are different than the functions you add to the ViewSet class.
APIView: you add functions for the particular HTTP method you want to support on your endpoint. Ex: GET, POST, PUT, PATCH, DELETE
ViewSet: you would add functions that represent actions that you'd perform on a typical API. Ex: LIST, CREATE, RETRIEVE, UPDATE
Viewsets and APIView both allow us to write logic for end point but Viewsets dont define functions which map to HTTP methods instead map to common API object actions
Related
I'm learning about the Django Rest Framework. And there are two concepts that from my point of view are almost the same, and they are used in different scenarios.
rest_framework mixins I think that they are used when we use viewsets.
And rest_framework generics are used with APIViews.
What is the difference between these two components?
The generics and mixin modules are indeed different, yet they are inter-related.
Django Rest Framework (DRF) separates ReSTful API / HTTP verb behaviour from Django model operations and organises a set of abstract/base classes for each. The ReSTful functionality is in APIView, GenericAPIView and ViewSetMixin. The Model related operations are implemented in the mixin module.
DRF then makes use of Python's multiple inheritance, and the "mixin" pattern, to combine these together into higher-level classes that are both useable and extensible.
The generic views and the concrete ModelViewSet both inherit from APIView in addition to composing functionality via the mixin classes.
Though not related to the question, the following observation about ViewSets may be helpful...
The following is the intro to ViewSets on the DRF site that might make things seem more complicated than they really are...
A ViewSet class is simply a type of class-based View, that does not provide any method handlers such as .get() or .post(), and instead provides actions such as .list() and .create().
The method handlers for a ViewSet are only bound to the corresponding actions at the point of finalizing the view, using the .as_view() method.
Rather than inheriting the ViewSet directly, in many cases, it will make the most sense to inherit a ModelViewSet and combine it with a DefaultRouter. The ModelViewSet obtains the method handlers via the various mixin classes, and the DefaultRouter provides the 'action' function mapping.
In combination, all the basic REST actions can be performed on a given Model, with very little code.
So, I have a view that inherits from APIView, I've defined get, post and delete methods.
My urls.py:
path('projects/', projects.ProjectView.as_view()),
path('projects/create/', projects.ProjectsView.as_view()
But right now I can make a request with any method accessing these API's. For example, I can create a project going to 'projects/' and I can delete a project going to 'projects/create/'.
Is there a way to specify what methods I wanna use for a specific url? When a user goes to 'projects/' I want only the 'get' method to be allowed for this url.
On classy way to do it is to inherit from generic-view
Your ProjectView should inherit from RetrieveAPIView and ProjectsVIew from CreateAPIView
And you could probably rename your views to something more explicit.
How to prefer which one of generics and viewset to use?
in other words when should I use generics and when should I use viewset for building api.
I know that they do the same thing, but viewset has routers, so in what situation generics are better than viewset?
They are different, let's see.
DRF has two main systems for handling views:
APIView: This provides methods handler for http verbs: get, post, put, patch, and delete.
ViewSet: This is an abstraction over APIView, which provides actions as methods:
list: read only, returns multiple resources (http verb: get). Returns a list of dicts.
retrieve: read only, single resource (http verb: get, but will expect an id in the url). Returns a single dict.
create: creates a new resource (http verb: post)
update/partial_update: edits a resource (http verbs: put/patch)
destroy: removes a resource (http verb: delete)
Both can be used with normal django urls.
Because of the conventions established with the actions, the ViewSet has also the ability to be mapped into a router, which is really helpful.
Now, both of this Views, have shortcuts, these shortcuts give you a simple implementation ready to be used.
GenericAPIView: for APIView, this gives you shortcuts that map closely to your database models. Adds commonly required behavior for standard list and detail views. Gives you some attributes like, the serializer_class, also gives pagination_class, filter_backend, etc
GenericViewSet: There are many GenericViewSet, the most common being ModelViewSet. They inherit from GenericAPIView and have a full implementation of all of the actions: list, retrieve, destroy, updated, etc. Of course, you can also pick some of them, read the docs.
So, to answer your question: DRY, if you are doing something really simple, with a ModelViewSet should be enough, even redefining and calling super also is enough. For more complex cases, you can go for lower level classes.
Hope to have helped you!
My golden rule for this is to use generics whenever I have to override the default methods to accomplish different specifications from list and details views.
For instance, when you have different serializer classes for listing your resources and for retrieving a resource details by id I consider that using generics is a better option since probably these two endpoints' logic is going to evolve separately. Keep in mind is a good practice to maintain different logics decoupled.
When your endpoint is very simple and you don't need to customize logic between list/create and retrieve/update/delete operations you can use viewset, but yet having in mind it may be good to separate it in two views in case these operations' logic start growing in different paths.
So i am now on a project where i have to customize flask-admin interface. I see two decortors that are important. The #expose decorator and the #action decorator. so my question is, where is the difference between them. For me it looks like they can do the same things. When o use #action and when to use #expose ?
#expose is used for rendering views onto one object, eg show/edit a user.
Use this decorator to expose views in your view classes. Link to documentation
#action is used for rending views on more than one object, eg Adding a user to a course (school).
Use this decorator to expose actions that span more than one entity (model, file, etc) Link to documentation.
For more understanding (im not an expert) read the Flask-admin documentation. It is highly recommended that you have a read and understand it, especially if you have joined a project that involves using flask-admin.
I'm learning Django REST Framework (http://tomchristie.github.io/rest-framework-2-docs/, we're still on version 2.4). Is it correct to define a class like this, for instance:
class UserView(generics.RetrieveUpdateDestroyAPIView,
generics.ListCreateAPIView,
viewsets.GenericViewSet):
# ... rest of class
In other words, is it correct or possible to use *ViewSet and *APIView mixins/classes together, or are they intended as two wholly separate concepts, not to be combined?
I don't think it is advisable to use both together. They were built for different purposes.
As per the docs,
ListCreateAPIView:
Used for read-write endpoints to represent a collection of model
instances.
Provides get and post method handlers.
Extends: GenericAPIView, ListModelMixin, CreateModelMixin
RetrieveUpdateDestroyAPIView:
Provides get, put, patch and delete method handlers.
Extends: GenericAPIView, RetrieveModelMixin, UpdateModelMixin,
DestroyModelMixin
GenericViewSet:
The GenericViewSet class inherits from GenericAPIView, and provides
the default set of get_object, get_queryset methods and other generic
view base behavior, but does not include any actions by default.
ModelViewSet:
The ModelViewSet class inherits from GenericAPIView and includes
implementations for various actions, by mixing in the behavior of the
various mixin classes.
The actions provided by the ModelViewSet class are .list(),
.retrieve(), .create(), .update(), and .destroy().
With ModelViewSet you can achieve all the CRUD operations that you intend to use with your above code snippet.
If you want a custom functionality i.e not all the method handlers, you can use generic views. But, if you want all the method handlers, then viewsets comes to your rescue. You can even browse through the rest framework code and see that mixins inherited in generic API views are a subset of mixins inherited in Viewsets.
Viewsets basically bundles those views together.
You can just do the following and achieve what you were intending to do in the first place:
class UserView(viewsets.ModelViewSet):
.....
In all versions of Django REST framework, the generic API views and ViewSet classes are distinctly separate, but the mixins can be shared across them. This is because the viewsets actually inherit from the generic classes in the first place.
As stated before, you can use the generic mixins though if you want to build a viewset with only a few supported methods, or if you want to override one of them on your own.
class UserView(mixins.CreateModelMixin, mixins.ListModelMixin,
mixins.RetrieveModelMixin, mixins.DestroyModelMixin,
mixins.UpdateModelMixin,
viewsets.GenericViewSet):
Don't forget that Django REST framework does provide a ModelViewSet and ReadOnlyModelViewSet base class that you can use as well.