The process of custom serialization, single check and group check of data, serialization process: ORM operation to get the data, and then serialize the data into data that can be used by the front desk and return it to the front desk.
from rest_framework.response import Response from django.conf import settings from rest_framework.views import APIView from. import models class UserV1APIView(APIView): def get(self,request,*args,**kwargs): pk = kwargs.get('pk') if pk: user_dic = models.User.objects.filter(is_delete=False,pk=pk).values('username','sex','img').first() #Serialized if not user_dic: return Response({ 'status':1, 'msg':'pk error' },status=400) user_dic['img'] ='%s%s%s'%(settings.BASE_URL,settings.MEDIA_URL,user_dic.get('img')) return Response({ 'status': 0, 'msg':'ok', 'results':user_dic }) else: user_query = models.User.objects.filter(is_delete=False).values('username','sex','img') #Serialized for user_dic in user_query:#user_query list set dictionary user_dic['img'] ='%s%s%s'%(settings.BASE_URL,settings.MEDIA_URL,user_dic.get('img')) user_list = list(user_query) return Response({ 'status': 0, 'msg':'ok', 'results': user_list })
1) Set the serialization field, the field name and field type should correspond to the attribute name of the model class to be processed (only the types involved in serialization do not need to set conditions)
2) There are fields in the model class, but there is no corresponding field in the serialization. This type of field does not participate in the serialization
3) Custom serialization field (Method 1), the field type is SerializerMethodField(), the value is provided by the get_custom field name (self, model_obj) method, and the general value is related to the model object (model_obj) involved in serialization
#View class from. import serializers class UserV2APIView(APIView): def get(self,request,*args,**kwargs): pk = kwargs.get('pk') if pk: user_obj = models.User.objects.filter(is_delete=False, pk=pk).first() if not user_obj: return Response({ 'status': 1, 'msg':'pk error' }, status=400) user_ser = serializers.UserSerializer(user_obj,many=False)#many defaults to False # user_dic['img'] ='%s%s%s'% (settings.BASE_URL, settings.MEDIA_URL, user_dic.get('img')) user_obj_data = user_ser.data return Response({ 'status': 0, 'msg':'ok', 'results': user_obj_data }) else: # Encapsulate the fields provided by the object and the entire serialization process to form a serialization class user_query = models.User.objects.filter(is_delete=False).all() user_ser = serializers.UserSerializer(user_query, many=True) user_list_data = user_ser.data return Response({ 'status': 0, 'msg':'ok', 'results': user_list_data }) #Custom serialization class serializers from rest_framework import serializers from django.conf import settings from. import models class UserSerializer(serializers.Serializer): # 1) The field name and field type should correspond to the processed model class # 2) Fields that are not provided will not participate in serialization to the front desk # 3) You can customize the serialization field, use method serialization, the method fixes two parameters, the second parameter is the model object that participates in the serialization username = serializers.CharField() # It is not recommended that the custom field name be the same as the database field name, it is better to use the return value of the get_custom field name method to provide the field value # sex = serializers.SerializerMethodField() # It is not recommended to name it like this gender = serializers.SerializerMethodField() def get_gender(self,obj): return obj.get_sex_display() #Note: In the advanced serialization and advanced view classes, drf helps us process sub-resources such as pictures by default icon = serializers.SerializerMethodField() def get_icon(self,obj): return'%s%s%s'% (settings.BASE_URL, settings.MEDIA_URL, obj.img)
1) There is no difference between the system check field and the custom check field definition:
Field = serializers. field type (condition)
2) Custom check fields cannot write data directly to the database, they are only responsible for the check before the data is written to the database.
3) All fields can be verified by setting corresponding local hooks. The setting method of local hooks: validate_ field name (self, field value value)
Rule: The verification pass directly returns the value, the verification fails, the verification failure message is thrown: ValidationError('error information')
4) A serialization class has a global hook that can perform global verification on all fields. The method of use: validate(self, dictionary of all field values attrs)
Rule: return attrs directly if verification is successful, and throw verification failure message if verification fails: ValidationError({'Exception Field','Error Information'})
5) Rewrite the create method to write the new data into the database, and return the successfully written data object
6) Rewrite the update method to write the modified data into the database, and return the successfully modified data object
#View class from. import serializers class UserV2APIView(APIView): def get(self,request,*args,**kwargs): pk = kwargs.get('pk') if pk: user_obj = models.User.objects.filter(is_delete=False, pk=pk).first() if not user_obj: return Response({ 'status': 1, 'msg':'pk error' }, status=400) user_ser = serializers.UserSerializer(user_obj,many=False)#many defaults to False # user_dic['img'] ='%s%s%s'% (settings.BASE_URL, settings.MEDIA_URL, user_dic.get('img')) user_obj_data = user_ser.data return Response({ 'status': 0, 'msg':'ok', 'results': user_obj_data }) else: # Encapsulate the fields provided by the object and the entire serialization process to form a serialization class user_query = models.User.objects.filter(is_delete=False).all() user_ser = serializers.UserSerializer(user_query, many=True) user_list_data = user_ser.data return Response({ 'status': 0, 'msg':'ok', 'results': user_list_data }) #单增 def post(self,request,*args,**kwargs): request_data = request.data user_ser = serializers.UserDeSerializer(data=request_data) #Call deserialization class if user_ser.is_valid(): user_obj = user_ser.save()#Write to database return Response({ 'status':0, 'msg':'ok', 'results':serializers.UserSerializer(user_obj).data # Return the reserialized data of the user object obtained in the library to the front desk }) else: return Response({ 'status':1, 'msg':user_ser.errors, })
#Inherit the serializers.Serializer class custom deserialization class of drf class UserDeSerializer(serializers.Serializer): #drf Check field username = serializers.CharField(min_length=3,max_length=16,error_messages={ 'min_length':'too short', 'max_length':'too long' }) password = serializers.CharField(min_length=3,max_length=16) # Fields not defined here do not participate in deserialization. If defined here, they must participate in deserialization (but you can not deserialize by setting required=False) # required=False field, if the front desk does not provide data, the default value is used, then the field will not be deserialized; if the front desk provides the data of the field, the data will be verified, and the data will be verified after verification Deserialize, and then write it to the database; no field is defined here, regardless of whether the front desk passes a value to the field, the default value is written to the database sex = serializers.BooleanField(required=False) # The data type and field name of the custom check field are the same as the fields in the models class, but the check field only checks the data re_password = serializers.CharField(min_length=3,max_length=16) # Partial hook: # Method validate_validated field name (self, validated field data) # Validation rule: the value will be returned directly after the validation, and the validation failure message will be thrown if the validation fails def validate_username(self,value): if'b' in value.lower(): raise serializers.ValidationError('A cannot appear in the name') return value def validate(self, attrs): re_password = attrs.pop('re_password')#pop will first take out the content to be popped, and then pop password = attrs.get('password') if password != re_password: raise serializers.ValidationError({'re_password':'The two passwords are not consistent'}) return attrs # In the view class, call the save method of the serialization class to write data to the database, and the save method will call the create and update methods of the Serializer class to write the data to the database. # But the Serializer class only defines empty create, update and other methods of operating the database. We need to rewrite these methods of the database to complete the operation of writing data to the database. def create(self, validated_data): return models.User.objects.create(**validated_data) # instance is the object to be modified, validated_data represents the data used to modify the instance after verification def update(self, instance:models.User, validated_data): #Do not modify user name validated_data.pop('username') models.User.objects.filter(pk=instance.id).update(**validated_data) return instance
If we want to use the serializer corresponding to the Django model class, DRF provides us with the ModelSerializer model class serializer to help us quickly create a Serializer class.
ModelSerializer is the same as regular Serializer, but provides:
Serialization and deserialization are achieved by inheriting the ModelSerializer class:
1) The serialization class inherits ModelSerializer, so it needs to be configured in the configuration class Meta
2) Model configuration: binding serialization related Model table
3) Fields configuration: use pluggable settings for all fields involved in serialization and deserialization
4) Extra_kwargs configuration: There are three types of system fields: read-only (read_only), write-only (write_only), readable and writable (when not set)
Whether the field must be filled in: required Optional field: configure in extra_kwargs, no need to set required, default required=False Read-only and write-only operations are used to participate in the serialization and deserialization of the fields, and do not directly affect the read and write of the database, so we can set the confirmation password and other fields to write-only, when using the global hook to take it out Remove it from the hook's attrs while proceeding.
5) Custom serialization fields: The first type (not recommended): Use SerializerMethodField() in the serialization class to achieve
The second (advocate): use @property to achieve in the model class, pluggable such as the following model class and serialization class
#Model Class username = models.CharField(max_length=64, verbose_name='username', blank=True, unique=True) password = models.CharField(max_length=64, verbose_name='password') sex = models.IntegerField(choices=SEX_CHOICES, default=0, verbose_name='gender') img = models.ImageField(upload_to='img', default='img/default.png', verbose_name='avatar') # During development, the data will not be deleted directly, but controlled by the field is_delete = models.BooleanField(default=False, verbose_name='Whether to log out') # Database data storage, generally records the first storage time of the data, sometimes it also records the last update time created_time = models.DateTimeField(auto_now_add=True, verbose_name='Created Time') # The second type of custom serialization field (pluggable, recommended) @property def gender(self): return self.get_sex_display() @property def icon(self): from django.conf import settings return'%s%s%s'% (settings.BASE_URL, settings.MEDIA_URL, self.img) class Meta: # Configuration class, which provides configuration information for the class to which it belongs db_table ='user' verbose_name_plural ='User table'
The so-called pluggable means that the field can be serialized and deserialized by default when it is added to the fields, but the premise is that the fields in the models must be customized. If it is a custom serialized field, the default is read_only, and cannot be modified, customized If the field is not pluggable, it can be deserialized but only deserialized (for data verification) cannot be written to the database.
#Serialization class class UserModelSerializer(serializers.ModelSerializer): #Validation rules can only be set at the time of definition, or set in the hook, and the setting in extra_kwargs is invalid re_password = serializers.CharField(min_length=3, max_length=16, write_only=True) class Meta: model = models.User # fields adopt pluggable settings for all participating serialization and deserialization fields fields = ('username','gender','icon','password','sex','re_password') extra_kwargs = { 'username': {# The system field does not set read_only and write_only, both will participate by default 'min_length': 3, 'max_length': 10, 'error_messages': { 'min_length':'too short', 'max_length':'too long' } }, 'gender': { 'read_only': True, # The custom serialization field is read_only by default, and cannot be modified, and can be omitted }, 'password': { 'write_only': True, }, 'sex': {# The fields with default values like sex are optional fields ('required': True can make them required fields) 'write_only': True, #'required': True } }
6) Custom deserialization fields:
#It is the same as the Serializer class, and the verification rules can only be set at the time of definition, or set in the hook, and the setting in extra_kwargs is invalid re_password = serializers.CharField(min_length=3, max_length=16, write_only=True) #Custom deserialization field is the same as system field setting rules, so write_only must be set to True
7) Local hooks, global hooks are the same as the Serializer class
# The local and global hooks are the same as the Serializer class, and are indented the same as Meta def validate_username(self, value): if'g' in value.lower(): raise serializers.ValidationError('There can be no g in the name') return value def validate(self, attrs): password = attrs.get('password') re_password = attrs.pop('re_password') if password != re_password: raise serializers.ValidationError({'re_password':'The two passwords are not consistent'}) return attrs #Verification rules: Local hook verification success returns value directly, failure message throws failure information, #Global hook verification success returns attrs, failure throws verification failure information
8) No need to rewrite create and update methods
The create and update methods of ModelSerializer are already written and will be called when the user_obj = user_ser.save() method is executed.
The complete view class, serialization class, and models class codes that are serialized and deserialized by inheriting the ModelSerializer class are as follows. The code realizes the query to the database through the browser and the single increase of data:
#View class class UserV3APIView(APIView): # Single check group check def get(self, request, *args, **kwargs): pk = kwargs.get('pk') if pk: user_obj = models.User.objects.filter(is_delete=False, pk=pk).first() if not user_obj: return Response({ 'status': 1, 'msg':'pk error', }, status=400) user_ser = serializers.UserModelSerializer(user_obj, many=False) return Response({ 'status': 0, 'msg':'ok', 'results': user_ser.data }) else: user_query = models.User.objects.filter(is_delete=False).all() user_ser = serializers.UserModelSerializer(user_query, many=True) return Response({ 'status': 0, 'msg':'ok', 'results': user_ser.data }) # Single increase def post(self, request, *args, **kwargs): user_ser = serializers.UserModelSerializer(data=request.data) if user_ser.is_valid(): # Warehousing user_obj = user_ser.save() return Response({ 'status': 0, 'msg':'ok', 'results': serializers.UserModelSerializer(user_obj).data }) else: return Response({ 'status': 1, 'msg': user_ser.errors, })
#Serialization class class UserModelSerializer(serializers.ModelSerializer): # The first type of custom serialization field: this field must be set in fields # gender = serializers.SerializerMethodField() # def get_gender(self, obj): # return obj.get_sex_display() # The usage of the custom deserialization field is the same as the Serializer class, and the rules can only be set in this statement or in the hook. The setting in extra_kwargs is invalid. # Note: Custom deserialization fields and system fields have the same setting rules, so write_only must be set re_password = serializers.CharField(min_length=3, max_length=16, write_only=True) class Meta: model = models.User # fields adopt pluggable settings for all participating serialization and deserialization fields fields = ('username','gender','icon','password','sex','re_password') extra_kwargs = { 'username': {# The system field does not set read_only and write_only, both will participate by default 'min_length': 3, 'max_length': 10, 'error_messages': { 'min_length':'too short', 'max_length':'too long' } }, 'gender': { 'read_only': True, # The custom serialization field is read_only by default, and cannot be modified, and can be omitted }, 'password': { 'write_only': True, }, 'sex': {# The fields with default values like sex are optional fields ('required': True can make them required fields) 'write_only': True, #'required': True } } # Local and global hooks have the same usage as the Serializer class, and are indented the same as Meta def validate_username(self, value): if'g' in value.lower(): raise serializers.ValidationError('There can be no g in the name') return value def validate(self, attrs): password = attrs.get('password') re_password = attrs.pop('re_password') if password != re_password: raise serializers.ValidationError({'re_password':'The two passwords are not consistent'}) return attrs
#Model Class from django.db import models class User(models.Model): SEX_CHOICES = ( (0,'Female'), (1,'Male'), ) username = models.CharField(max_length=64, verbose_name='username', blank=True, unique=True) password = models.CharField(max_length=64, verbose_name='password') sex = models.IntegerField(choices=SEX_CHOICES, default=0, verbose_name='gender') img = models.ImageField(upload_to='img', default='img/default.png', verbose_name='avatar') # During development, the data will not be deleted directly, but controlled by the field is_delete = models.BooleanField(default=False, verbose_name='Whether to log out') # Database data storage, generally records the first storage time of the data, sometimes it also records the last update time created_time = models.DateTimeField(auto_now_add=True, verbose_name='Created Time') # The second type of custom serialization field (pluggable, recommended) @property def gender(self): return self.get_sex_display() @property def icon(self): from django.conf import settings return'%s%s%s'% (settings.BASE_URL, settings.MEDIA_URL, self.img) class Meta: # Configuration class, which provides configuration information for the class to which it belongs db_table ='user' verbose_name_plural ='User table' def __str__(self): # Don’t link tables here, for example, the admin page may crash return self.username