Django Rest framework(drf) 快速入门(二) -- 使用Serializer大幅简化代码量

Python

咕鸽框架 更新2020年05月22日 99 5530字 CID:P11

0x00 前言

接上次代码, 完成了数据的获取和提交, 本次将会用到Serializer对数据进行定义, 从而大幅减少代码量, 提高代码复用率

0x01 编写get的Serializer

在同目录下建立一个serializers.py, 效果如图

在这里插入图片描述

在里面填上如下代码

from rest_framework import serializers
from .models import Config


class ConfigListSerializer(serializers.ModelSerializer):  # ModelSerializer和model相对应
    class Meta:
        model = Config  # 设置对于model
        fields = ('nickname',  # 设置需要序列化的字段
                  'title',
                  'desc',
                  'config',
                  'user_like',
                  'last_download')

serializers.ModelSerializer说明这个serializers关联一个Model, 在Metamodel里和model进行绑定, 然后再fields内定义需要被序列化的字段
然后在view.py内改写函数get

class ConfigView(APIView):
    def get(self, request):
        config_list = Config.objects.all()  # 取所有数据
        serializer = ConfigListSerializer(config_list, many=True)  # 建立serializer实例
        return Response(serializer.data, status=status.HTTP_200_OK)

成功了

在这里插入图片描述

但是我们也发现一件事, user_like返回的是一个列表, 但是我们只想返回一个具体的数量, 解决办法就是覆盖掉user_like字段, 如代码

from rest_framework import serializers
from .models import Config


class ConfigListSerializer(serializers.ModelSerializer):  # ModelSerializer和model相对应
    user_like = serializers.SerializerMethodField()  # 点赞数

    def get_user_like(self, obj):
        return obj.user_like.all().count()

    class Meta:
        model = Config  # 设置对于model
        fields = ('nickname',  # 设置需要序列化的字段
                  'title',
                  'desc',
                  'config',
                  'user_like',
                  'last_download')

再次打开发现已经被覆盖了

在这里插入图片描述

0x03 编写Post的Serializer

首先看看我们post需要哪些数据
Config里面只有uid user nickname title desc config user_like create_time last_download
get请求里我们差不多要把这些数据全部返回回来, 但是在请求post的时候, 因为create_time last_download user_like 等是系统自动添加的, 不需要表单提供, 而且post需要请求Config里没有的username sign数据, 于是我们对Serializer进行改写

from rest_framework import serializers
from .models import Config, User
from .utils import md5


class ConfigListSerializer(serializers.ModelSerializer):  # ModelSerializer和model相对应
   # 需要魔改的字段, 配合get_user_like食用
   user_like = serializers.SerializerMethodField(read_only=True)

   # 新增的数据库里没有的, 自定义的字段
   username = serializers.CharField(write_only=True)
   sign = serializers.CharField(write_only=True)

   """
   此函数用于配合SerializerMethodField, 具体就是xxx前面加上一个get_, 这样就可以对字段进行个性化设置, 如+1什么的
   """
   def get_user_like(self, obj):
       return obj.user_like.all().count()

   """
   此函数用于验证表单是否有问题,  没问题返回attrs, 否则raise serializers.ValidationError()
   """
   def validate(self, attrs):
       if md5(attrs['username'] + "123456") != attrs["sign"]:  # 验证签名
           raise serializers.ValidationError("用户签名错误")
       return attrs

   """
   此函数用于重载save, 建议在此处写上保存入数据库操作, 后面有用
   """
   def save(self, **kwargs):
       user = User.objects.get_or_create(username=self.validated_data["username"], sign=self.validated_data["sign"])[0]
       Config.objects.get_or_create(  # 存储配置
           user=user,
           nickname=self.validated_data["nickname"],
           title=self.validated_data["title"],
           desc=self.validated_data["desc"],
           config=self.validated_data["config"],
       )

   class Meta:
       # 设置对于model
       model = Config

       # 用于表示所有的出现的字段
       fields = ('uid', 'nickname', 'title', 'desc', 'config', 'user_like', 'last_download', 'username', 'sign')
       # 此字段用于设置fields的权限 read_only: 只有get里有   write_only: 只有post里有
       extra_kwargs = {
           "uid": {"read_only": True},
           "user_like": {"read_only": True},
           "last_download": {"read_only": True},
       }

首先在serializers里补齐post里需要的字段usernamesign, 并在Meta.fields里添加, 由于他们是只在post里有用, get并不需要, 于是加上write_only=True属性. 然后在Meta里新增字段extra_kwargs, 用于声明所有只读属性(只有get里出现的)
新增函数validate用于验证表单是否错误, 在这里你甚至可以对参数进行一些调整, 比如交换, 别忘了最后要return attrs, 如果出错则抛出serializers.ValidationError
然后新增函数save, 可以发现我们把view里的保存到数据库搬到这里做了, 这样可以使view于database分离, 而且咋后面的mixin中有更大的好处

编写post视图

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import Config
from .serializers import ConfigListSerializer


class ConfigView(APIView):
   def get(self, request):
       config_list = Config.objects.all()  # 取所有数据
       serializer = ConfigListSerializer(config_list, many=True)  # 建立serializer实例
       return Response(serializer.data, status=status.HTTP_200_OK)  # 返回序列化内容

   def post(self, request):
       serializer = ConfigListSerializer(request.data)  # 从表单里取出内容
       if serializer.is_valid():  # 验证表单是否有问题, 就是调用了validate函数
           serializer.save()  # 没问题的话则保存对象
           return Response({"data": "创建完成"}, status=status.HTTP_201_CREATED)
       return Response({"error": "表单错误"}, status=status.HTTP_400_BAD_REQUEST)

可以看到视图也没有多少内容了, 然而这还可以进一步精简, 还能只用几行代码添加许多预设功能, 比如过滤/分页, 这些都在后面的Mixinviewsets, 这里才能体会到drf强大的实力

版权声明:
本文基于《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》许可协议授权
文章链接:http://blog.z31.xyz/index.php/archives/11/ (转载时请注明本文出处及文章链接)

评论

咕鸽框架

咕鸽框架

⭐相关推荐

PyQt5快速入门教程(三) --- 常用控件

PyQt5快速入门教程(三) --- 常用控件回顾上节课Qt Designer基础用法让python显示我们画的ui本节课内容熟悉常用控件的功能熟悉常用控...

PyQt5快速入门教程(二) --- Qt Designer基础操作

PyQt5快速入门(二)回顾上节课搭建PyQt5环境测试PyQt5环境本节课内容Qt Designer基础用法让python显示我们画的ui让咱们开始吧!...

PyQt5快速入门(一) --- 环境配置与第一个程序

PyQt5快速入门(一)前言为什么选择PyQt5作为GUI框架?API与Qt一致, 学会PyQt后再使用qt很简单开发迅速, 可视化操作,使用design...

PyQt5中在QListWidget自定义Item的方法

PyQt5中在QListWidget自定义Item的方法效果图自定义一个Item新建一个QWidget对象在QWidget内添加Layout在Layout...

✨当下热门