Generic Views vs APIView vs Viewsets, vs ModelViewsets - python

I just started learning Django Rest Framework and I get to now about 4 concepts APIView, Viewsets, Modelviewsets, GenericView. What is the difference between them and which of them is more efficient to use in the development of rest APIs and why?

There is no standard but you can start with this simple strategy:
Several actions in one class and basic CRUD ---> Viewset (ModelViewSet and ReadOnlyModelViewSet are most useful)
Specific action on a model class ---> Generic Views (RetrieveModelMixin, ListAPIView, UpdateModelMixin, DestroyModelMixin, CreateModelMixin)
If you want to write all create, update, ... methods yourself you can use APIView and write them in your get, post, put, ... methods (Difference between APIView & GenericAPIView is only you cant use some builtin methods in your class , like queryset, serializer_class, ... )
And if you want to write everything from scratch you can write your apis in function base
Most of the times you have to write you apis with Generic Views & If you learn all of the Generic APIView best practices, it has so much power and your will be so clean, readable and scalable
Buy if you have simple Models you can use Viewset
I use GenericAPIView in normal APIs & use APIView in the custom ones (like most of APIs in Admin Panel)

Related

Django form validation vs DRF serializer validation

I'm new to APIs creation in django.
I checked DRF serializers and I found them useful when manipulating models in DB. My APIs don't use models they are based on forms.
So my question is : what can I get more from using DRF validators then using django forms validators in my views ? maybe the content type is more convenient (application/x-www-form-urlencoded vs application/json) ?
DRF's serializers are nicely integrated within the framework. Whether they are models based or not, you will have a nice browsable UI to play with for free and you can get OpenAPI schema generation. There are probably other things I did not think of.
What serializers can do that forms can't:
Nested data - although you can get some results with formsets.
Hyperlinked relational fields
Difference between an empty field and a blank field - HTML forms can't do that
out of the box integration with generic class based views or viewsets
Please note that your can still benefit from DRF even if you are not using serializers. DRF parts are loosely coupled.

Difference between ViewSet, ModelViewSet and APIView

What are the advantages of ViewSet, ModelViewSet and APIView. In the django-rest-framework documents it is not clear, it does not say when to use ViewSet, ModelViewSet and APIView. I want to implement an API that will have a business logic in there, a great business logic with data processing as well, what should be used for this case?
I researched a lot and managed to understand a little about routers and urlpatterns but I didn't understand which one about views.
Summarizing: on one hand you have the APIView, which is the most generic of the three, but also in which you must do almost all business logic 'manually'. You have the class methods mapping http methods (get, post, ...) plus some class attributes to configure things like authentication, rendering, etc.
Often you'll be developing endpoints to interact with resources (entities, like Users, Products, Orders, etc.) via CRUD operations, and that is what ViewSet is for: they have more semantic class methods like list, create, retrieve ... that the router can then automatically map to urls and http methods at the expense of making some assumptions: for example, the retrieve assumes the http call to be GET /you_resource/<pk>. It is more rigid than a generic APIView but it takes away from you some boilerplate/manual config that you would have to repeat again and again in most cases.
One step further is the ModelViewSet, which is an extension of the ViewSet for when you are working with Django models. Just specifying a serializer_class and a queryset you have all the CRUD operations of the ViewSet ready to go. Obviously, you can also add your own methods to a ViewSet or customize the behavior of its default methods.
In my experience, it pays off to use ViewSets. The code looks cleaner and you avoid some boilerplate code. The assumptions it makes are reasonable, and I would even say that you probably will end up with a cleaner API design following them.

Difference between django.core serializers and Django Rest Framework serializers

I am now learning Django and I just heard about Django Rest Framework (DRF). I was wondering what is the difference between the django.core serializers and the rest_framework serializers. Yes, I know DRF is for APIs.
django.core serializers are meant for the purpose of serializing entire model instances into XML, JSON, or YAML, and vice versa. They don't do anything besides just serializing.
DRF's serializers are specifically for converting model instances into JSON objects when dealing with data from HTML forms or API requests. Thus, serialization is not always a smooth or straightforward process, as you may be passed illegitimate or incomplete data, or fields of the form may not correspond in an obvious way to the fields of the corresponding model(s). For this reason, DRF allows you to create custom subclasses of serializers.Serializer in order to clean and validate data that is passed to the server. This also allows you to customize the manner in which the data is stored in the model instance. See the documentation here.

How to get APIViews and ViewSets to show on API Root when using Router with Django REST Framework?

I recently started using DRF and am wondering how to get the automatically generated API Root provided by a Router to display endpoint routes that don't come from ViewSet-based views.
In my case, I have some non-ViewSet (generic) class-based views (ListAPIView and RetrieveAPIView) in my views.py that I would like to appear in my API Root.
I am open to alternative solutions to this, e.g. should I abandon ViewSets and implement those endpoints differently, etc.
I think the best way here is to:
keep using all your preferred ViewSets / Generic* / Mixins / bare views. This is where the real work happens.
rewrite the APIRoot-View (it is not that complex, see the source).
either use the urlconfig or extend the DefaultRouter to make DRF use your APIRoot-View.

How to utilize django generic view?

For example, I want a page, which will let user add data for different categories of goods.
Like:
Model: Category is foreign key of item
Category1(detail url):
Item 1(detail url):
Date(textbox), Amount(textbox), Price(textbox)
Item 2:
...
Category2:
...
Save button, add more button, etc...
Since this is an example, I what those thing all display in a page.
I don't mind hard writing them with normal functions, but I wonder if I can utilize the views, since if they are so heavily introduced and developed, they might be powerful. So why not utilize it?
Can anyone tell me tricks about how to use them or we shouldn't use them if we want more functionality?
Django's generic views cover a lot of common use cases. For example:
CreateView - a view for creating an instance of a model
UpdateView - a view for updating an existing instance of a model
DeleteView - a view for deleting an existing instance of a model
DetailView - a view for displaying the details of an exsting instance of a model
ListView - a view for displaying a list of instances of a model
There are more around if you need them, and they cover the majority of views you are likely to need. You can also extend them to meet your needs quite easily. As a general rule of thumb, they make such a huge difference to how quickly you can get something built that I would recommend using them by default, and only switching over to writing your own views when absolutely necessary. If you haven't yet learned them, I think doing so will be a very good investment of your time - you will make up the time spent very quickly. For a lot of view types, it's just a case of specifying the model, setting up the URLs and the template, and you're done.
If you need to pass through additional data, then you can extend the generic view in question and override the get_context_data() method. If the same needs to be applied to several different generic views, you can create a mixin that includes that method and include it in that generic view.
For views that include forms, like the CreateView and UpdateView, as Drewness said, you can pass through a ModelForm instance to tell it what form to use, and that form can itself be overriden, so you still have a lot of control over what the form will do. For instance, you might define the following form:
from django.forms import ModelForm
class CategoryForm(ModelForm):
exclude = ['date_created']
And the following view
from django.views.generic.edit import CreateView
class CategoryCreateView(CreateView):
model = Category
form_class = CategoryForm
The Django tutorial covers generic views pretty well.
You can use Django's ModelForm with a FormView.
Then all of the fields in your model will be available in your form and in your form view. You should also look at mixins. Mixins allow you to use combinations of class-based views.
Finally, if you want to use more than one form (model) in a view you can use a FormSet.

Categories