Django (45) the use of drf serialization class (Serializer)

Preface

In the previous article, we talked about serialization, this article will take everyone to implement the following serialization

Serializer

We use the serialization class Serializer, let’s look at the source code structure, here is recommended to use the pycharmleft navigation bar Structure, you can clearly see the structure of a file, as shown below


We will find that Serializerinherits from BaseSerializerand SerializerMetaclass, but Serializerclass and no createmethods and updatemethods, so we used 必须to manually define these two methods

Ready to work

1. Create a new project drf_demo, create a new app in the project, create a drf_appnew file in the app urls.py, the project structure is as follows

2. models.pyWrite the following code in the file

class Student(models.Model):     SEX_CHOICES = (        (1,'男'),        (2, '女')    )     name = models.CharField(max_length=20, verbose_name='姓名')    age = models.IntegerField(null=True, blank=True, verbose_name='年龄')    sex = models.IntegerField(choices=SEX_CHOICES, default=1, verbose_name='性别')     class Meta:        db_table = "student"

3. Write the following codes in drf_demo.urls.pyand drf_app.urls.pyrespectively

# drf_demo.urls.pyurlpatterns = [    path('drf/', include('drf_app.urls')),] # drf_app.urls.pyapp_name = "drf_app"urlpatterns = [    path('student/', views.student),]

4. Comment out the settings.pyfile and add 2 apps in itMIDDLEWAREdjango.middleware.csrf.CsrfViewMiddlewareINSTALLED_APPS

'rest_framework','drf_app'

5. Enter the following command on the command line to map the orm object to the database

python manage makemigrationspython manage migrate

6. Write the serialization class. Generally, we create new serializers.pyfiles in the app project, and then we can formally write the serialization class.

Serialization class writing

# Serializer的构造函数的参数:# 1. instance:需要传递一个orm对象,或者是一个queryset对象,用来将orm转成json# 2. data:把需要验证的数据传递给data,用来验证这些数据是不是符合要求# 3. many:如果instance是一个queryset对象,那么就需要设置为True,否则为False class StudentSerializer(serializers.Serializer):    # 序列化提供给前台的字段个数由后台决定,可以少提供    # 但是提供的数据库对应的字段,名字一定要与数据库字段相同     id = serializers.IntegerField(read_only=True)    name = serializers.CharField(required=True, max_length=200)    sex = serializers.IntegerField(required=True)    age = serializers.IntegerField(required=True)     def create(self, validated_data):        """        根据提供的验证过的数据创建并返回一个新的`Student`实例        """        return Student.objects.create(**validated_data)     def update(self, instance, validated_data):        """        根据提供的验证过的数据更新和返回一个已经存在的`Student`实例。        """        instance.name = validated_data.get('name', instance.name)        instance.age = validated_data.get('name', instance.age)        instance.sex = validated_data.get('name', instance.sex)        instance.save()        return instance     # 局部钩子 validate_要校验的字段名(self, 当前要校验字段的值)    def validate_name(self, value):        if 'j' in value.lower():            raise exceptions.ValidationError("名字非法")        return value     def validate_sex(self, value):        if not isinstance(value, int):            raise exceptions.ValidationError("只能输入int类型")        if value != 1 and value != 2 :            raise exceptions.ValidationError("只能输入男和女")        return value     # 全局钩子 validate(self, 系统与局部钩子校验通过的所有数据)    def validate(self, attrs):        age = attrs.get('age')        sex = attrs.get('sex')        if age < 22 and sex == 1:            raise exceptions.ValidationError({"age&sex": "男的必须22周岁以上才能结婚"})        return attrs

Our above code first defines the serialized field, the parameters in the field are inherited from the Fieldclass, the parameters are as follows

def __init__(self, read_only=False, write_only=False,             required=None, default=empty, initial=empty, source=None,             label=None, help_text=None, style=None,             error_messages=None, validators=None, allow_null=False):
  • read_only: When to Truerepresent this field can only be read, only be used when data is returned when.
  • write_only: When to Truerepresent this field can only write, only new data or update data will be used when the time. For example, our account password is only allowed to be submitted by the user, and the back-end does not return the password to the front-end
  • required: When to Trueindicate when the fields are required, do not fill status code 400 is returned
  • default: The default value, nothing to say
  • allow_null: When is Truethe time, it allows the field is empty

After that, we defined partial hooks to verify special fields. For example, according to requirements, the user's gender can only be entered as male and female. At this time, you can define a hook. Of course, it will drfautomatically do some verification for us, such as required The field is a inttype, you enter the stringtype, it will automatically trigger the system error, we don’t need to define it, we will test it later

Next, we define a global hook, which means to verify the entire data. The most suitable scenario is to enter the password repeatedly. Generally, when we register, we need to enter the password twice, and the second time is used to confirm. This scenario suitable for use on a global hook
finished writing serializersafter our last step, the preparation of view function, as follows:

def student(request):    # 获取所有的学生    if request.method == "GET":        # 创建一个queryset对象        stu = Student.objects.all()        # 将对象序列化为dict         stu_data = StudentSerializer(instance=stu, many=True).data        return JsonResponse(status=200, data=stu_data, safe=False)    elif request.method == "POST":        data = JSONParser().parse(request)        serializer = StudentSerializer(data=data)        # 校验字段是否符合规范        if serializer.is_valid():            # 符合则保存到数据库            serializer.save()            return JsonResponse(data=serializer.data, status=200)        return JsonResponse(serializer.errors, status=400)

test

The test is divided into GETrequests and POSTrequests

GET request

We open the interface test tool postmanor apifox, here as apifoxan example, input 127.0.0.1:8000/drf/student/, and get the following results

[    {        "id": 1,        "name": "jkc",        "sex": 1,        "age": 18    },    {        "id": 2,        "name": "mary",        "sex": 2,        "age": 20    }]

It shows that the serialization is successful, and jsonthe format of the database data is successfully returned to the front desk

POST request

Also open the interface tool, enter 127.0.0.1:8000/drf/student/, bodyselect the jsonformat in the, enter the following data

{    "name": "aaaa",    "sex": 2,    "age": 18}

The results of the operation are as follows:

{    "id": 13,    "name": "aaaa",    "sex": 2,    "age": 18}

It shows that our deserialization is also successful. Friends can check the database during practice. There will be one more piece of data like this.
Next, can we trigger the hook function?

Test validate_name hook

Enter test data

{    "name": "jjj",    "sex": 2,    "age": 18}

The returned results are as follows:

{    "name": [        "名字非法"    ]}

Test validate_sex hook

Enter test data

{    "name": "kkk",    "sex": 3,    "age": 18}

The returned results are as follows:

{    "sex": [        "只能输入男和女"    ]}

Test the default input type is wrong

Enter test data

{    "name": "kkk",    "sex": "???",    "age": 18}

The returned results are as follows:

{    "sex": [        "请填写合法的整数值。"    ]}

The default required items for the test are not filled in

Enter test data

{    "name": "kkk"}

The returned results are as follows:

{    "sex": [        "该字段是必填项。"    ],    "age": [        "该字段是必填项。"    ]}

Test global hooks

Enter test data

{    "name": "kkk",    "sex": 1,    "age": 18}

The returned results are as follows:

{    "age&sex": [        "男的必须22周岁以上才能结婚"    ]}

to sum up

  1. Set required and optional serialization fields, and set verification rules
  2. Provide a local hook function for the field that needs additional verification. If the field is not stored in the library and does not participate in the global hook verification, the value can be taken out for verification
  3. Provide global hook functions for fields that have a union relationship. If some fields are not stored in the library, the value can be taken out for verification
  4. Rewrite the createmethod, complete the data storage work that passed the verification, and get the new object