DRF序列化器基本使用
- 对用户提交的数据进行校验
- 从数据库中取到数据进行序列化,转化为JSON格式返还给前端
1 序列化数据
1.1 Serializer
# models.py
from django.db import modelsclass Depart(models.Model):"""部门表"""title = models.CharField(verbose_name="标题", max_length=32)number = models.CharField(verbose_name="代号", max_length=16, default=1)
# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import serializers
from api import modelsclass DemoSerializer(serializers.Serializer):id = serializers.IntegerField()title = serializers.CharField()number = serializers.CharField()class DemoView(APIView):def get(self, request):# 1.数据库获取多条数据# queryset = models.Depart.objects.all()# ser = DemoSerializer(instance=queryset, many=True) 内部会循环queryset的每一个对象,再返回# 2.数据库获取单条数据instance = models.Depart.objects.filter(id=1).first()ser = DemoSerializer(instance=instance, many=False)print(type(ser.data), ser.data)return Response(ser.data)
1.2 ModelSerializer
from django.db import modelsclass Depart(models.Model):"""部门表"""title = models.CharField(verbose_name="标题", max_length=32)number = models.CharField(verbose_name="代号", max_length=16, default=1)
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import serializers
from api import modelsclass DemoSerializer(serializers.ModelSerializer):class Meta:model = models.Depart# fields = "__all__" # 所有字段# fields = ['id', 'title', 'number'] # 指定字段exclude = ["id"] # 剔除某个字段class DemoView(APIView):def get(self, request):# 1.数据库获取多条数据# queryset = models.Depart.objects.all()# ser = InfoSerializer(instance=queryset, many=True)# 2.数据库获取单条数据instance = models.Depart.objects.filter(id=1).first()ser = InfoSerializer(instance=instance, many=False)print(type(ser.data), ser.data)return Response(ser.data)
很显然,如果要对数据表中的字段进行序列化,使用ModelModelSerializer
是要比Serializer
更简洁一些的。
1.3 自定义字段和参数
在ModelModelSerializer
和Serializer
中都可以自定义字段,并传入一些相关参数。
from django.db import modelsclass Depart(models.Model):"""部门表"""title = models.CharField(verbose_name="标题", max_length=32)number = models.CharField(verbose_name="代号", max_length=16, default=1)class UserInfo(models.Model):name = models.CharField(verbose_name="姓名", max_length=32)gender = models.SmallIntegerField(verbose_name="性别", choices=((1, "男"), (2, "女")))role = models.ForeignKey(verbose_name="角色", to="Role", on_delete=models.CASCADE)ctime = models.DateTimeField(verbose_name="创建时间", auto_now_add=True)
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import serializers
from api import modelsclass InfoSerializer(serializers.ModelSerializer):gender = serializers.CharField(source="get_gender_display")role = serializers.CharField(source="role.title")ctime = serializers.DateTimeField(format="%Y-%m-%d")other_name = serializers.CharField(source="name")mine = serializers.SerializerMethodField()class Meta:model = models.UserInfofields = ['id', 'name', 'gender', "role", 'ctime', "other_name", "mine"]def get_mine(self, obj):return "x-x-{}".format(obj.name)class InfoView(APIView):def get(self, request):queryset = models.UserInfo.objects.all()ser = InfoSerializer(instance=queryset, many=True)print(type(ser.data), ser.data)return Response(ser.data)
1.4 序列化类嵌套
主要是ORM类中对应ForeignKey
和 ManyToManyField
的字段进行序列化。
- 基于
SerializerMethodField
自定义方法对关联表数据进行序列化 - 基于嵌套的序列化类实现
# models.py
from django.db import modelsclass Role(models.Model):title = models.CharField(verbose_name="标题", max_length=32)order = models.IntegerField(verbose_name="顺序")class Tag(models.Model):caption = models.CharField(verbose_name="名称", max_length=32)class UserInfo(models.Model):name = models.CharField(verbose_name="姓名", max_length=32)gender = models.SmallIntegerField(verbose_name="性别", choices=((1, "男"), (2, "女")))role = models.ForeignKey(verbose_name="角色", to="Role", on_delete=models.CASCADE)ctime = models.DateTimeField(verbose_name="创建时间", auto_now_add=True)tags = models.ManyToManyField(verbose_name="标签", to="Tag")
# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import serializers
from api import modelsclass RoleSerializer(serializers.ModelSerializer):class Meta:model = models.Role# fields = "__all__"fields = ["id", 'title']class TagSerializer(serializers.ModelSerializer):class Meta:model = models.Tagfields = "__all__"class InfoSerializer(serializers.ModelSerializer):role = RoleSerializer()tags = TagSerializer(many=True)class Meta:model = models.UserInfofields = ['id', 'name', "role", "tags"]class InfoView(APIView):def get(self, request):queryset = models.UserInfo.objects.all()ser = InfoSerializer(instance=queryset, many=True)print(type(ser.data), ser.data)return Response(ser.data)
1.5 序列化类继承
# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import serializers
from api import modelsclass MySerializer(serializers.Serializer):more = serializers.SerializerMethodField()def get_more(self, obj):return "123"class InfoSerializer(serializers.ModelSerializer, MySerializer):class Meta:model = models.UserInfofields = ["id", "name", 'more']class InfoView(APIView):def get(self, request):instance = models.UserInfo.objects.all().first()ser = InfoSerializer(instance=instance, many=False)print(type(ser.data), ser.data)return Response(ser.data)
2 数据校验
对用户发来的请求数据进行校验 + 保存
GET请求 -> 获取数据(列表)
POST请求 -> 新增数据
PUT请求 -> 更新数据
2.1 内置校验
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import serializersclass InfoSerializer(serializers.Serializer):title = serializers.CharField(required=True, max_length=20, min_length=6)order = serializers.IntegerField(required=False, max_value=100, min_value=10)level = serializers.ChoiceField(choices=[("1", "高级"), (2, "中级")])class InfoView(APIView):def post(self, request):ser = InfoSerializer(data=request.data)if ser.is_valid():return Response(ser.validated_data)else:return Response(ser.errors)# def post(self, request):# ser = InfoSerializer(data=request.data)# ser.is_valid(raise_exception=True) 如果校验失败,则返回错误;校验成功,继续向后走(本质与上文一样)# return Response(ser.validated_data)
2.2 正则校验
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import serializers
from django.core.validators import RegexValidator, EmailValidatorclass InfoSerializer(serializers.Serializer):title = serializers.CharField(required=True, max_length=20, min_length=6)order = serializers.IntegerField(required=False, max_value=100, min_value=10)level = serializers.ChoiceField(choices=[("1", "高级"), (2, "中级")])# email = serializers.EmailField()email = serializers.CharField(validators=[EmailValidator(message="邮箱格式错误")])more = serializers.CharField(validators=[RegexValidator(r"\d+", message="格式错误")])code = serializers.CharField()class InfoView(APIView):def post(self, request):ser = InfoSerializer(data=request.data)if ser.is_valid():return Response(ser.validated_data)else:return Response(ser.errors)
2.3 钩子校验
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import serializers
from rest_framework import exceptionsclass InfoSerializer(serializers.Serializer):title = serializers.CharField(required=True, max_length=20, min_length=6)order = serializers.IntegerField(required=False, max_value=100, min_value=10)code = serializers.CharField()def validate_code(self, value):print(value)if len(value) > 6:raise exceptions.ValidationError("字段钩子校验失败")return value# 上面所有字段全部校验成功之后再执行validatedef validate(self, attrs):print("validate=", attrs)# api_settings.NON_FIELD_ERRORS_KEY 全局配置错误信息(遇到错误时non_field_errors替换为相应的字段)# raise exceptions.ValidationError("全局钩子校验失败")return attrsclass InfoView(APIView):def post(self, request):ser = InfoSerializer(data=request.data)if ser.is_valid():return Response(ser.validated_data)else:return Response(ser.errors)
2.4 ModelSerializer校验
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import serializers
from rest_framework import exceptions
from api import models
from django.core.validators import RegexValidatorclass RoleSerializer(serializers.ModelSerializer):more = serializers.CharField(required=True)class Meta:model = models.Rolefields = ["title", "order", "more"]extra_kwargs = {"title": {"validators": [RegexValidator(r"\d+", message="格式错误")]},"order": {"min_value": 5},}def validate_more(self, value):return valuedef validate(self, attrs):return attrsclass InfoView(APIView):def post(self, request):ser = RoleSerializer(data=request.data)if ser.is_valid():return Response(ser.validated_data)else:return Response(ser.errors)
2.5 校验+保存
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import serializers
from rest_framework import exceptions
from api import models
from django.core.validators import RegexValidatorclass RoleSerializer(serializers.ModelSerializer):more = serializers.CharField(required=True)class Meta:model = models.Rolefields = ["title", "order", "more"]extra_kwargs = {"title": {"validators": [RegexValidator(r"\d+", message="格式错误")]},"order": {"min_value": 5},}def validate_more(self, value):return valuedef validate(self, attrs):return attrsclass InfoView(APIView):def post(self, request):ser = RoleSerializer(data=request.data)if ser.is_valid():ser.validated_data.pop("more")ser.save() # ser.save(v1=123,v2=234)return Response(ser.validated_data)else:return Response(ser.errors)