Django-DRF serializer definition and use

Serializer Serializer

1. Serialization: The serializer will convert the model object into a dictionary, which will be converted into a JSON format string after the Response
2. Deserialization: The data sent by the client will be converted into a dictionary after the Request, and the serializer can Convert the dictionary into a model
3. Deserialization: complete the data verification function

# diango 服务终端
python manage.py shell

define serializer

class StudentSerializer(serializers.Serializer):
    '''
	    在视图内获取了模型类里面的值(QuerySet类型)
	    实现的结果等同于基于QuerySet内容进行for循环这个序列化器,将QuerySet中的每个对象属性值
	    赋给以下和对象属性名相同的字段作为值
    '''

    id = serializers.IntegerField() # 接收模型类对象的id属性值
    name = serializers.CharField() # 接收模型类对象的name属性值
    sex = serializers.CharField()
    age = serializers.IntegerField()
    phone = serializers.CharField()

The essence is equivalent to receiving the value in the form of key:value
1. The view passes {"name":'jack'} to the serializer
2. The serializer defines the name field to receive the value of 'jack'

The serializer can not only be defined for the database model class, but also can be defined for the data of the non-database model class. The serializer exists independently of the database.

The Serializer object uses

Serializer class constructor

Serializer(instance=None, data=empty, **kwarg)

1. When used for serialization, pass the model class object into the instance parameter
2. When used for deserialization, pass the data to be deserialized into the data parameter
3. Except for the instance and data parameters, when constructing the Serializer object , you can also add additional data through the context parameter, such as:

serializer = StudentSerializer(name, context={
    
    'request': request})

The data attached through the context parameter can be obtained through the context property of the Serializer object.

1. When using the serializer, you must pay attention. After the serializer is declared, it will not be executed automatically. We need to call it in the view.
2. The serializer cannot receive data directly, so we need to pass the used data when creating the serializer object in the view.
3. The field declaration of the serializer is similar to the form system we used earlier.
4. When developing a restful API, the serializer will help us convert the model data into a dictionary.
5. The view provided by DRF will help us convert the dictionary into json, or convert the data sent by the client into a dictionary.

Serializer usage phase

1. When the client requests, use the serializer to complete the deserialization of the data.
2. When the server responds, the serializer can be used to complete the serialization of the data.

How to use the serializer

Basic use
Complete the serialization of the value by passing the value to the serializer, DRF will serialize it into JSON format, and then respond

from rest_framework.views import APIView
from rest_framework.response import Response

from app01 import serializer
from app01 import models

class BookView(APIView):
    def get(self,request):
    	# 获取所有学生对象保存在QuerySet查询集里面
        student_list = models.Student.objects.all()

		# 如果传递给序列化器的是一个QuerySet查询集类型的数据,那么则需要增加参数many=True
        ser = serializer.StudentSerializer(instance=student_list,many=True)

		# 序列化后的数据保存在序列化器对象的data属性内
        return Response(ser.data)

# views
class SkrAutoView(GenericAPIView):
    def get(self, request):
        queryset = UserInfo.objects.all()
        print(f'queryset:{
      
      queryset}')
        print("============")
        ser = SkrSerializers(instance=queryset, many=True)
        print(ser.data)
        user_list = []
        for user in queryset:
            user_list.append({
    
    
                "id": user.id,
                "name": user.name,
                "sex": user.sex,
                "age": user.age,
                "phone": user.phone
            })
        return JsonResponse(user_list, safe=False, json_dumps_params={
    
    "ensure_ascii": False})

# Serializers
class SkrSerializers(serializers.Serializer):
    SEX_CHOICES = (
        (0, '未知'),
        (1, '男'),
        (2, '女')
    )
    id = serializers.IntegerField(read_only=True)
    name = serializers.CharField(max_length=10, error_messages={
    
    'max_length': '名称不能超过10位数哦'}, required=False)# 非必传
    sex = serializers.ChoiceField(choices=SEX_CHOICES, label="性别", required=False)
    age = serializers.IntegerField(max_value=99, error_messages={
    
    'max_value': '输入的年龄不能大过99岁!!'},
                                   required=False)
    phone = serializers.CharField(required=False)
    
    def create(self, validated_data):  # 校验合格的数据
        userinfo = UserInfo.objects.create(**validated_data)  # 将字典形式的数据拆分成关键字形式
        return userinfo  # 返回新增数据后的对象,Response进行序列化成JSON格式响应到客户端

The fields we define in the serializer determine what kind of data can be responded to the client. If only the id field is defined, then the field receives the id attribute of the object in the QuerySet, and naturally only the id field is returned to the client. the data

Use of the deserializer - post request
Usage scenario: When there are certain requirements for the passed in data, it must be verified, and the serializer can be used to achieve this purpose.

# 序列化器
from rest_framework import serializers
from rest_framework.exceptions import ValidationError

from app01 import models

class StudentSerializer(serializers.Serializer):

    # required字段可以不传值(因为在模型类里面它是一个自增的字段)
    id = serializers.IntegerField(required=False)

    name = serializers.CharField(max_length=10,error_messages={
    
    'max_length':'名称不能超过10位数哦'},required=False)

    sex = serializers.CharField(required=False)
    age = serializers.IntegerField(max_value=99,error_messages={
    
    'max_value':'输入的年龄不能大过99岁!!'},required=False)

    phone = serializers.CharField(required=False)

    def validate_name(self, data): # name字段的局部钩子
        '''
        :param data: 当前字段的值
        :return:
        '''

        if data.startswith('zz'):
            raise ValidationError('名称不能以zz开头')
        return data

    def validate(self, attrs): # 全局钩子
        '''
            中间可以有校验过程
        :param attrs: attr是一个字典的形式,可以拿到任意字段的值
        :return:
        '''
        return attrs
	
	    def create(self, validated_data):  # 校验合格的数据
        userinfo = UserInfo.objects.create(**validated_data)  # 将字典形式的数据拆分成关键字形式
        return userinfo  # 返回新增数据后的对象,Response进行序列化成JSON格式响应到客户端

# 视图层
from rest_framework.views import APIView
from rest_framework.response import Response

from app01 import serializer
from app01 import models

class BookView(APIView):
    def get(self,request):
        student_list = models.Student.objects.all()
        ser = serializer.StudentSerializer(instance=student_list,many=True)
        return Response(ser.data)

    def post(self,request):
        # request.data属性内具备了post请求发送的数据,将数据传递给序列化器
        ser = serializer.StudentSerializer(data=request.data)

        if ser.is_valid(): # 判断是否通过序列化器的校验

            '''
            如果调用序列化器没有传递instance参数,且我们调用了save方法,
            那么同时也会执行save方法内的create方法,并进行新增数据,但DRF并不允许我们这么做
            DRF框架需要我们重写该方法才能新增数据,所以我们通常会在序列化容器内重写create方法
            '''
            ser.save()

            return Response(ser.data) # 经过序列化器后的数据都保存在data属性内

        else:
            # 校验不合格的错误信息会集成在序列化器对象的errors属性内
            return Response({
    
    'status':102,'error':'您输入的内容不合法,请重新输入','msg':ser.errors})

The deserializer uses the - put request

# views
# 笔者重写了一下Response方法,每次都能够返回状态码
class MyResponse(Response):
    def __init__(self, data=None, status=100):
        super().__init__(status=status, data=data)

        self.data = {
    
    'status': status, 'msg': data}
        

class BookDetailView(APIView):
	def put(self, request, id):
	    obj = models.Student.objects.filter(pk=id).first()
	    response = {
    
    }
	    if obj:
	        ser = serializer.StudentSerializer(instance=obj,data=request.data)
	
	        if ser.is_valid():  # 判断数据是否符合我们校验规则
	            ser.save()
	            # 当向序列化器传递了instance参数时,且调用了save方法,那么就会执行其内的update方法,所以DRF依旧需要我们重写update方法
	
	            response['status'] = 200
	            response['data'] = ser.data
	        else:
	            response['status'] = 101
	            response['data'] = ser.errors  # 返回错误信息
	
	    else:
	        response['status'] = 404
	        response['data'] = '修改的数据不存在'
	
	    return Response(response)

# 序列化器
class StudentSerializer(serializers.Serializer):
	# code....>>>
	
	def update(self, instance, validated_data):
	'''
	:param instance: 更新的对象
	:param validated_data: 更新的数据
	:return:
	'''
	
	instance.__dict__.update(validated_data) # 对象里面key与put请求提交过来的key相同的话,值进行更新
	
	instance.save()
	
	return instance # 将对象返回,序列化成JSON格式响应到页面

delete request

class BookDetailView(APIView):
 	def delete(self,request,id):
        obj = models.Student.objects.filter(pk=id)
        response = {
    
    }
        if obj:
            obj.delete()
            response['status'] = 200
            response['data'] = '' # 删除成功返回空
        else:
            response['status'] = 404
            response['data'] = '需要删除的数据不存在'

        return Response(response)

Fields and parameters commonly used by serializers

insert image description here
Note: Using these fields in the serializer converts the received fields into a certain type.

The value of the id field is int type, and we receive it through id=serializer.CharField(), then the value returned to the view is of string type.

insert image description here

Use serializers to customize fields, names

When the data is passed to the serializer, we can define the field content, which fields to return, and custom fields in the serializer

# demo
ph = serializers.SerializerMethodField()
def get_ph(self,obj): # 针对哪个序列化器字段的操作
    # obj拿到的是传入到当前序列化器的对象
    return obj.phone + "9999" # 将对象的phone属性值赋给ph字段,然后返回到视图

custom field name

# 把phone字段改名叫做ppp
ppp = serializers.CharField(source='phone') # ppp字段值来自哪个字段

Customize the data returned to the view, and the use of read_only and write_only parameters

  • The data obtained by the view depends on the fields of the serializer. When our serializer defines the following content
class StudentSerializer(serializers.Serializer):
	id = serializers.IntegerField(required=False)
	name = serializers.CharField()
	sex = serializers.CharField()
	age = serializers.IntegerField()
	# phone = serializers.CharField()
  • The view can only convert the 4 fields returned by the serializer definition into a JSON format response to the client,
    insert image description here
  • And if the field is set with the write_onely=True parameter, then the field can only be used to receive data each time, and will not be returned to the view.
class StudentSerializer(serializers.Serializer):
    id = serializers.IntegerField(required=False)
    name = serializers.CharField()
    sex = serializers.CharField(write_only=True) # 不会返回到视图
    age = serializers.IntegerField()

  • Setting write_only is just not used to return to the front end, it still needs to pass the value when calling
    insert image description here
  • When a field is set with the read_only=True parameter, it can only be used as a response to the client every time it is returned to the view, and the POST or PUT request cannot affect the field.
class StudentSerializer(serializers.Serializer):
    id = serializers.IntegerField(required=False)
    name = serializers.CharField()
    sex = serializers.CharField(read_only=True)
    age = serializers.IntegerField()

insert image description here

  • It is not possible to add or modify values ​​for fields with read_only=True
    insert image description here

Model class serializer

Custom serializers require us to manually create each field (too cumbersome), and model class serializers can help us save this tedious step.
DRF provides a model class serializer: Model Serializer. The role is to simplify the definition of the serializer corresponding to the Django model class.

ModelsSerializer is the same as regular Serializer, but provides the following main functions:

1. Automatically generate a series of fields based on the model class (we don't need to manually define them one by one)
2. Automatically generate Validators for the Serializer based on the model class, such as the unique validator for the field
3. No need to rewrite create() and update() Implement new and modified functions.
The serializer that inherits the ModelSerializer class is based on the Meta inner class to complete some field definitions:

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Student # 指明参照的模型类
        fields = '__all__' # 包含模型类的所有字段
        # fields = ('id','name') 只使用id、name字段作为序列化字段
        # exclude = ('sex') 排除sex字段使用其它作为序列化字段
        # read_only_fields = ('sex','age') 只读字段,即仅用于序列化输出的字段
        # extra_kwargs,为字段增加一些参数
        extra_kwargs = {
    
    
            'create_date':{
    
    'required':False,'read_only':True}
        }
	'''
		可以自定义一些字段,返回给视图,但是需要设置成read_only=True,required=True,不然每次向这个序列化传的值也要包括这些自定义的字段,导致无法入库。
		这里可以与继承Serializer类定义完字段以后使用方式相同。
		ddd = serializer.CharField(source='name')
		注意:一定要写在Meta类外面
	'''

And when we add or modify data to the database with POST and PUT requests, we don't need to rewrite the create and update methods.
Here we replace the above StudentSerializer content with the following:

class StudentSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Student  # 指明参照的模型类
        fields = '__all__'  # 包含模型类的所有字段

        # 为字段添加一些参数
        extra_kwargs = {
    
    
            'create_date': {
    
    'required': False, 'read_only': True}
        }

Now you can directly submit a POST request to the backend, but you can
insert image description here
achieve the purpose of adding data without rewriting the create method. This is because ModelSerializer has helped us rewrite the create and update methods.

create and update methods

When using Serializer as a serializer inheritance class, we have two options for adding and modifying data:

1. Manually store the data in the database in is_valid
2. Rewrite the create and update methods to receive the filtered values, and then store them in the database,
but the above two are too troublesome, we need to manually store the data in the database, and the ModelSerializer class The create and update methods basically don’t need us to rewrite, unless we need to record the association between the two tables through the third table. In this case, even if the ModelSerializer class is inherited, the create or update method needs to be rewritten.

Our actual serializer usually uses the ModelSerializer class as inheritance, because the code using it can be written as less as possible compared to the Serializer class, and it looks more concise overall, followed by the create and update methods written by ModelSerializer for us, which avoids us Write more repetitive code! !

おすすめ

転載: blog.csdn.net/weixin_43587784/article/details/129091030