当前位置: 首页 > article >正文

Django REST Framework中的序列化器类和视图类

序列化器类

一、Serializer序列化类

Serializer是DRF的序列化器基类,提供基本功能,使用Serializer类需要自己定义字段名称和类型。

BookSerializer(Serializer):
	name = serializers.CharField()
	price = serlializers.IntegerField()
	date = serlializers.DateField()

Serializer序列化器类初始化的时候的几个参数说明:
instance这个指从数据库中读取的记录对应的对象,用于显示或者编辑中的现有
many如果是true,则指传递了多个对象
data用于收集通过post传上来的字典,用于新增或者编辑中的更新
Serializer序列化器提供了一个.save()接口用于保存数据,这个函数里面通过判断instance是否有值来确定是新增还是更新,如果有值则调用self.update(),如果没有值则调用self.create(),这两个方法需要自己实现,以满足用户的新增或者修改的逻辑。

self.create(self, validated_data)
self.update(self, instance, validated_data)

实现了这两个方法后,在客户类里面需要新增或者保存的时候,只需统一的调用serializer.save()就可以了。

二、ModelSerializer类

使用ModelSerializer类,就不用再自己定义字段名称和类型了,直接给出模型名称,指出需要序列化的字段即可。

BookSerializer(ModelSerlizer):
	class Meta:
		model	= Book
		fields	= [“name”, “date”] # 这里可以自己定义需要的字段,__all__表示所有字段,也可以自己定义字段名称

使用ModelSerlializer类也不需要再自己定义create()和update()方法了,ModelSerlializer类已经实现了这两个函数的定义。

视图类

django里面的视图实际上是业务逻辑存放的地方,也就是“功能”,并不是页面样式。
而业务的功能无非就是这5种:增、删、改、查(列表)、查(详情)
DRF里面提供了三大类的类:API、mixin、ViewSet,API类的类提供接口(get、post、put、update、delete),mixin提供功能,ViewSet负责包装。

一、CBV视图,基于类的视图

django的原生视图是基于函数的,也就是FBV。CBV是基于类的,继承自View类。View类中有两个重要的函数:

View.dispatch()
View.as_view()

在View.as_view()函数中,又定义了一个子函数view(),as_view()会返回这个函数。在基于函数(FBV)的视图模式中,urls.py文件中指向的就是函数,而在基于类的视图(CBV)中,urls.py文件中指向的是类的as_view()函数,注意这里是加了括号的,就是说是要直接执行这个函数的,而这个函数的执行结果,是里面的子函数vews()。子view()函数会调用View.dispatch()函数,用于通过反射,指向在客户类中定义的get(),post(),put(),delete()等http方法的函数。
提示:CBV相对于FBV,改变了函数的组织形式,FBV是自己定义函数,通过路径找到该函数。CBV是统一使用http的method,用过method名称(get、post、put、update、delete),找到以该名称定义的函数,实现增删改查查。这也就是RESTFul。

二、APIView

APIView(View)类中也定义了以下两个函数:

APIView.dispatch()
APIView.as_view()

其中,as_view()函数调用了csrf_exempt()函数用来处理跨域请求
使用APIView类也需要自己定义:get(),post(),put(),delete()等http方法函数。
相比django原生的CBV,这里的dispatch()函数包装了request,提供了一个用于API的强大的request。另外还初始化了三个基础功能:认证、权限、限流
提示:相对于基本CBV,APIView定制了request,专门用于API应用。另外还调用了三个基础功能:认证、权限、限流。

三、通用视图类GenericAPIView

通用视图类GenericAPIView(APIView)
引入了两个变量:
queryset表示数据集
serializer_class 表示序列化器类
get、post、put、delete等函数还需要有
提示:
1、这个类需要配合其他类,通过多继承的方式使用。
2、有了数据集和序列化器类,我们还需要操作这些数据的方法:get、post、put…,下面的mixin系类分别定义了这些方法。以便根据自己的需求组合使用。

四、mixin混合类

mixins 是一种代码复用机制,允许我们将多个组件共享的逻辑提取到一个独立的对象中,从而提高代码的可维护性和重用性。
这里新增了以下几个类:CreateModelMixin、ListModelMixin、RetrieveModelMixin、UpdateModelMixin、DestroyModelMixin,每一个类里面只实现了类名称中动词的方法。
名称里都有model,就是操作model,实现了和数据库交互的具体逻辑。
注意这里的5个方法和增删改查查中的5个方法(get、post、put、update、delete)名称不一致,需要再定义一下增删改查查方法,然后只需要在具体方法内返回对应的mixin方法即可。
例如,CreateModelMixin类实现了create方法,可以实现对数据库的增加操作
ListModelMixin类实现了list方法,可以实现对数据库的查询操作
RetrieveModelMixin类实现了retrieve方法,可以实现对数据库的查询操作
UpdateModelMixin类实现了update方法,可以实现对数据库的修改操作
DestroyModelMixin类实现了destroy方法,可以实现对数据库的删除操作
使用方法:在视图类中继承GenericAPIView类和以上几个类,然后在视图类中定义queryset和serializer_class属性
最后在urls.py中配置路径
例如:
urls.py

urlpatterns = [
 	path('houseku/', HouseKuList.as_view()),
]

views.py

class HouseKuList(generics.ListCreateAPIView, generics.GenericAPIView):
	queryset = HouseKu.objects.all()
 	serializer_class = HouseKuSerializer
	# 这里还要写get、post、delete等函数,用于对应Mixin里面的list、create等
	def get(self, request):
		return self.list(request) 
	def post(self, request):
		return self.create(request)

提示:GenericAPIView提供了queryset、serializer_class,mixin混合类提供了方法(但这些方法不对应的method名称)这两个组合在一起,就实现了相应的功能。

五、Mixin再封装,优化后的APIView

Mixin里面实现了list、create等方法,但是并没有对应http的method,DRF实现了进一步封装,创造了以下类:
ListCreateAPIView、RetrieveUpdateDestroyAPIView、ListAPIView、CreateAPIView、RetrieveAPIView、UpdateAPIView、DestroyAPIView
这里面的每一个类,实际上就是继承了对应的mixin类和GenericAPIView类,所以只要赋值给queryset、serializer_class就实现了一个完整的功能,如下:

class HouseKuViewSet(generics.ListCreateAPIView):
   queryset = HouseKu.objects.all()
   serializer_class = HouseKuSerializer

提示:每一个类都是完整的顶层类,变量赋值后就可以直接拿过来使用。

六、ViewSet

ViewSetMixin

对于前面的类,思路都是分成两个类(BookView用户列表,BookDetailView用于详细)来实现增post、删delete、改put、查get(用于列表)、查get(用于详情),到这里,就不用再写两个自定义的类了。可以合二为一,然后在urls.py里面as_view的参数里,把put、post、delete等method自定义的函数关联起来就可以了。
ViewSetMixin里面的as_view(action)方法可以加参数,用于指定method方法到自定义方法的映射。

path(“book/”, views.BookView.as_view({“get”:”get_all”, “post”:”add_object”})
path(“book/(?P<pk>\d+)”,views.BookView.as_view({“get”:”get_object”, “delete”:”delete_object”, “put”:”update_object”})

GenericViewSet(ViewSetMixin, GenericAPIView)

因为ViewSetMixin类只是提供了一个可以在as_view里定义action字典的这个功能,并没有实现任何逻辑,所以GenericViewSet这个类也没有提供任何逻辑,实际引入了queryset、serializer_calss两个变量。但是这个类再配合系列的ModelMixin类就实现了 create(), retrieve(), update(), partial_update(), destroy() and list() 操作。

class ModelViewSet(mixins.CreateModelMixin,
                   mixins.RetrieveModelMixin,
                   mixins.UpdateModelMixin,
                   mixins.DestroyModelMixin,
                   mixins.ListModelMixin,
                   GenericViewSet):

注意,这里实现的方法的名称也不是method动作名称,需要在urls.py里面定义字典:

urlpatterns = [
	path('viewset/user/', views.UserViewSet.as_view({'get': 'list', 'post': 'create'})),
	path('viewset/user/<int:pk>/', views.UserViewSet.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
]

七、示例

APIView

urls.py

urlpatterns = [
	path('user/', views.UserView.as_view()),
	path('user/<int:pk>/', views.UserDetailView.as_view()),
]

views.py

from rest_framework.views import APIView

class UserView(APIView):
    def get(self, request):
        users = User.objects.all()
        serializer = UserSerializer(users, many=True)
        return Response(serializer.data)

    def post(self, request):
        serializer = UserSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=201)
        return Response(serializer.errors, status=400)
        
class UserDetailView(APIView):
    def get(self, request, pk):
        user = User.objects.get(pk=pk)
        serializer = UserSerializer(user)
        return Response(serializer.data)

    def put(self, request, pk):
        user = User.objects.get(pk=pk)
        serializer = UserSerializer(user, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=400)

    def delete(self, request, pk):
        user = User.objects.get(pk=pk)
        user.delete()
        return Response(status=204)

GenericAPIView

需配合一系列的Mixin来使用
urls.py

urlpatterns = [
	path('mixin/user/', views.UserMixinView.as_view()),
	path('mixin/user/<int:pk>/', views.UserMixinDetailView.as_view()),
]

views.py

class UserMixinView(mixins.ListModelMixin,
                    mixins.CreateModelMixin,
                    generics.GenericAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer

    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)

class UserMixinDetailView(mixins.RetrieveModelMixin,
                          mixins.UpdateModelMixin,
                          mixins.DestroyModelMixin,
                          generics.GenericAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer

    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)
    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)

ListCreateAPIView、RetrieveUpdateDestroyApiView

urls.py

urlpatterns = [
	path('generic/user/', views.UserGenericView.as_view()),
	path('generic/user/<int:pk>/', views.UserGenericDetailView.as_view()),
]

views.py

class UserGenericView(generics.ListCreateAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer

class UserGenericDetailView(generics.RetrieveUpdateDestroyAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer

ViewSet

urls.py

urlpatterns = [
	path('viewset/user/', views.UserViewSet.as_view({'get': 'list', 'post': 'create'})),
	path('viewset/user/<int:pk>/', views.UserViewSet.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
]

到这里,已经将两个类合二为一了,最简洁,但是也最不灵活,适合用于不添加任何自己逻辑的增删改查查
views.py

class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer

http://www.kler.cn/a/590950.html

相关文章:

  • 基于深度学习的OCR+NLP,医疗化验单智能识别方案
  • MPC算法路径跟踪_Matlab实现
  • HTML基础内容2
  • C#运算符与表达式:从入门到游戏伤害计算实践
  • debian12.9 kde切到x11安装搜狗输入法遇到的问题
  • Docker Compose 和 Kubernetes(K8s)对比
  • 工作记录 2017-02-03
  • redis十大应用数据类型具体使用及其应用
  • 蓝桥杯每日五题第一日
  • 每日学习Java之一万个为什么(待补充)
  • LeetCode算法题(Go语言实现)_04
  • 【AVRCP】蓝牙协议栈深度解析:AVCTP互操作性核心机制与实现细节
  • 安全帽二维码:如何提升施工现场的安全管控效果
  • linux 命令 touch
  • 提示词工程化学习,方便用于dify
  • .NET8使用EF Core连接SQLite
  • Shell脚本中的弱治简写
  • 紧急通知:某平台泄露充电桩财富公式!5台×120kW=1.3年回本,年利润34.3万!速删前收藏 - 慧知开源充电桩平台
  • 234.回文链表
  • 【机器人-基础知识】标定 - IMU(Inertial Measurement Unit, 惯性测量单元)