1 9 view subclasses
The 9 view subclasses are a combination of GenericAPIView
and 5 view extension classes
Import through from rest_framework.generics import
, and when writing a view class, you only need to inherit the view subclass
ListAPIView
, only used to display allCreateAPIView
, add aListCreateAPIView
, display all and add oneRetrieveAPIView
, displays aDestroyAPIView
, delete an itemUpdateAPIView
, modify one itemRetrieveUpdateDestroyAPIView
, display, modify and delete an itemRetrieveDestroyAPIView
, display one item and delete one itemRetrieveUpdateAPIView
, display one item and modify one item
If you want to write one, some, or all of the five interfaces in the future, you only need to choose to inherit from different classes. You only need to configure two class attributes in the class.
1.1 View class
I want to write publish: an interface to query all, query a single item, modify an item, add an item, and delete an item.
class PublishView(ListCreateAPIView): queryset = Publish.objects.all() serializer_class = PublishSerializer class PublishDetailView(RetrieveUpdateDestroyAPIView): queryset = Publish.objects.all() serializer_class = PublishSerializer
1.2 Routing
The routing has not changed
path('publish/', PublishView.as_view()), path('publish/<int:pk>', PublishView.as_view()),
2 Viewset
Integrate views using the same library and serialization classes
2.1 ModelViewSet
View function
from rest_framework.viewsets import ModelViewSet class PublishView(ModelViewSet): queryset = Publish.objects.all() serializer_class = PublishSerialize
Routing
path('publish/', PublishView.as_view({<!-- -->'get':'list','post':'create'})), path('publish/<int:pk>', PublishView.as_view({<!-- -->'get':'retrieve','put':'update','delete':'destroy'})) ,
2.1.1 ModelViewSet source code analysis
-
There are query interfaces for all
get–list—-》Get all data, serialize–return -
Add a new item
post-create-》The new code we wrote before is the same
2.2 ViewSetMixin
ModelViewSet inherits five view extension classes and GenericViewSet. GenericViewSe inherits ViewSetMixin
, which overrides as_view()
ViewSetMixin
has been decided, and the way to write routes will change in the future.
Source code analysis
class GenericViewSet(ViewSetMixin, generics.GenericAPIView) # ViewSetMixin must be placed in front--" Ensure that the executed as_view is ViewSetMixin
The request comes, and the route is matched successfully-》Execute view(request) in as_view of ViewSetMixin
def view(request, *args, **kwargs): self = cls(**initkwargs) # Get the object from class instantiation--"Whose object is self?" PublishView self.action_map = actions # {'get':'list','post':'create'} # method: get # action: list for method, action in actions.items(): # list method handler = getattr(self, action) #Reflection list in PublishView object, got it # Reflection setting value #setattr (object of PublishView view class, get, list methods) # There will be a get method in the object of the PublishView view class, which is list setattr(self, method, handler) return self.dispatch(request, *args, **kwargs)
Summary
The routing is configured like this: PublishView.as_view({'get':'list','post':'create'})
In the future, when a get request comes in, what is essentially executed is the list method in the view class.
2.2.1 Write custom methods in the view class
In the future, the method names in the view class can be named arbitrarily, as long as the routing is properly mapped
from rest_framework.viewsets import ViewSetMixin,ViewSet
The inherited class is: as long as you inherit ViewSetMixin, you can name the methods in the view class arbitrarily and change the routing writing
ViewSetMixin
+APIView
=ViewSet
If there is no table related, just useViewSet
GenericViewSet
+ViewSetMixin
=ModelViewSet
If it is related to tables, useModelViewSet
View class
class UserView(ModelViewSet): queryset = UserInfo.objects.all() serializer_class = UserSerializer def book(self, request): return Response('from book')
Routing
path('book/', UserView.as_view({<!-- -->'post': 'login'}))
Access address
2.3 ReadOnlyModelViewSet
from rest_framework.viewsets import ReadOnlyModelViewSet
The interfaces written in the future only want to get a single item and get all, so inherit it.
2.4 Summary of classes in the view layer
1 Two view base classes
APIView and GenericAPIView
- Execution process of
APIView
:
Wrapping new ones, processing csrfrequeset, performing three major authentications, and handling global exceptions GenericAPIView
If you want to do serialization and deal with the database, just inherit it directly.- Class attributes
queryset
,serializer_class
- Methods
get_object
,get_queryset
,get_serializer
- Class attributes
2 5 view extension classes (not view classes)
Requires GenericAPIView to use
RetrieveModelMixin
To query an item, I wrote a methodretrieve
. The code is the same as the content of the get method we wrote before.CreateModelMixin
To add a new post, write a methodcreate
. The code is the same as the content of the new post method we wrote before.DestroyModelMixin
To delete an item, a methoddestroy
is written. The code is the same as the delete method we wrote before to delete an item.ListModelMixin
A methodlist
is written to query all. The code is the same as the content of the get method we wrote before to query allUpdateModelMixin
Modify one and write a methodupdate
. The code is the same as the content of the put method we wrote and modified before.
3 9 view subclasses
A combination of inheriting GenericAPIView + 5 view extension classes
Reference 1
ViewSet
-
ModelViewSet:
ViewSetMixin + GenericAPIView + 5 view extension classes
GenericViewSet + 5 view extension classes -
ViewSetMixin source code: Routing mapping configuration, the methods in the view class can be named casually in the future
Viewset: ViewSetMixin + APIView-“No need for serialization, the routing writing method has changed
GenericViewSet: ViewSetMixin + GenericAPIView–》Needs serialization, needs to use database, routing writing method changes
ReadOnlyModelViewSet: list and retrieve
3 Routing
It may be a bit troublesome to write and map the previous routes, so drf helped us encapsulate two routing classes -” which can help us quickly generate the mapping relationships we wrote before
Condition: Must inherit ViewSetMixin + APIView and its subclasses to automatically generate
Automatically generate routes: Automatic mapping is as follows:
{get’: list’, post’: create’}
{get’: retrieve’, put’: update’, delete’: destroy’}
3.1 How to use
Major premise: the view class must inherit ViewSetMixin
+ APIView
and its subclasses to be automatically generated
Steps for usage
#### 1 Import routing class from rest_framework.routers import SimpleRouter, DefaultRouter #### 2 Class instantiation to get the object router = SimpleRouter() #### 3 Automatically generate routes, call a certain method of the object, complete the corresponding relationship with the view class, and map the route router.register('publish', PublishView, 'publish') router.register('user',UserView,'user') ##### 4 Add the automatically generated route to the total route urlpatterns = urlpatterns + router.urls # Add the two lists directly ### The fourth step can be written like this, in urlpatterns #Add prefix to route path('api/v1/', include(router.urls)), # http://127.0.0.1:8008/api/v1/user/register/--->post
3.2 SimpleRouter, DefaultRouter
The difference between SimpleRouter and DefaultRouter
- The path generated by
DefaultRouter
has one more root path api-root DefaultRouter
will come with a default API root view and return a hyperlink response data containing all list views.
Use it from now on: SimpleRouter will do
3.3 action decorator
Write a custom method in the view class, roughly implemented as 2.2.1
The routing does not need to change, define it in the view class and use the action decorator
How to use
from rest_framework.decorators import action class UserView(ModelViewSet): queryset = UserInfo.objects.all() serializer_class = UserSerializer @action(methods=['POST'], detail=False) def register(self, request): back_dic = {<!-- -->'code': 200, 'msg': "Registration successful"} ser = self.get_serializer(data=request.data) if ser.is_valid(): ser.save() return Response(back_dic) else: return Response({<!-- -->'code': 200, 'msg': ser.errors})
Access address
The register method can be used through a specific access address and the post
method.
where user is the address using this class
action parameters
methods
: Request method, you can write multipledetail
: Whether there is an ID number in the path
http://127.0.0.1:8008/user/register/
detail=False
http://127.0.0.1:8008/user/4/register/
detail=True
3.4 Rewriting method
In the future, if you inherit ModelViewSet, you may also override many methods.
Rewrite list
class UserView(ModelViewSet): queryset = UserInfo.objects.all() serializer_class = UserSerializer # In the future, we may rewrite the list and make our own customizations. def list(self, request, *args, **kwargs): res = super().list(request, *args, **kwargs) return Response({<!-- -->'code': 200, 'msg': 'View all users successfully', 'result': res.data})
Rewrite get_serializer_class
It is a method in the GenericAPIView class. Whatever it returns, the serialization class will be used to continue the operation in the future.
class UserView(ModelViewSet): queryset = UserInfo.objects.all() serializer_class = UserSerializer def get_serializer_class(self, *args, **kwargs): if self.action == 'login': return LoginSerializer else: return self.serializer_class @action(methods=['POST'], detail=False) def login(self, request): back_dic = {<!-- -->'code': 200, 'msg': "Login successful"} # Use serialization class ser = self.get_serializer(data=request.data) if ser.is_valid(): for i in self.get_queryset(): if i.username == ser.data.get('username') and i.password == ser.data.get('password'): return Response(back_dic) back_dic['code'] = 1002 back_dic['msg'] = "User password is wrong" return Response(back_dic) else: return Response({<!-- -->'code': 200, 'msg': ser.errors})
Rewrite perform_create
Before saving the data, do some operations, such as writing logs
def perform_create(self, serializer): serializer.save()
3.4 Action parameter print(self.action) in the object of the view class
There is an action attribute in the object of the view class – it is a string of method names executed in a single request
Through action, you can limit which serialization class is used by a method in the view class.