preface
Over the past few years, I have been struggling in the it industry. Along the way, many have summarized some high-frequency interviews in the python industry. I see most of the new blood in the industry, and I still have all kinds of difficult questions for the answers to all kinds of interview questions or collection
Therefore, I developed an interview dictionary myself, hoping to help everyone, and also hope that more Python newcomers can really join the industry, so that Python fire does not just stay in advertising.
Wechat applet search: Python interview dictionary
Or follow the original personal blog: https://lienze.tech
You can also focus on WeChat official account and send all kinds of interesting technical articles at random: Python programming learning.
Serializer
Normal serializer
Response cannot directly return ORM data, so we need to serialize it. We can manually convert it into a dictionary or JSON * * *, or use the serializer provided by DRF. We generally recommend that you use the serializer *, which is more professional, simpler and more uniform in format
If you often use to encapsulate data into * * * JSON * * *, the common code model is like this
data = models.objects.all() json_ = {} for d in data: json_['age'] = d.age json_['name'] = d.name return Response(json_)
If there are too many fields, the workload will become more and more troublesome. Moreover, it is impossible to serialize field types such as time (DateTimeField and DateField) directly through * * * JSON * * *. You need to manually write * * JSON serializer, which is very troublesome. Therefore, DRF provides two more convenient serializers, ordinary serializer and model serializer
Writing method of ordinary serializer
from rest_framework import serializers
The ordinary serializer can convert the matched ORM data field into * * * JSON * * * data according to the given field, not only for a piece of data, but also for the result set corresponding to a * * QuerySet
For example, a curriculum has the following fields
class Course(models.Model): name = models.CharField(max_length=20, verbose_name='Course name') created = models.DateField(verbose_name='Course creation time') def __str__(self): return self.name
Test data can be added manually through the database
Then the ordinary serializer can be defined as follows, which can be supported according to the model class fields. It is very simple
class CourseSer(serializers.Serializer): name = serializers.CharField(max_length=20) created = serializers.DateField(auto_now_add=True)
Ordinary serializers can be defined not only for database model classes, but also for non database model classes. However, when defining model classes here, they need to be mapped one by one according to the model class fields
Normal serializer serialization
Serialization is to put ORM data into the serializer for processing, and generate * * * JSON * * * data object. The data attribute of the serializer object is the processed JSON data object
- Serialization of a single piece of data
The serialization of singleton data is very simple. You can directly pass in the query result through the parameter * * * instance * * * of the serializer class object
object = models.objects.get(pk=1) ser_data = Serializer(instance=object) ser.data # This is the JSON result of this data
- Serialization of multiple pieces of data
If you use some ORM methods such as * * * filter * * * and all to obtain the QuerySet result set instead of a separate data object, you need to pass in the many=True parameter to represent: Wow ~ 😲, A lot of data
objects = models.objects.all() ser_data = Serializer(instance=objects, many=True) ser_data.data # This is the JSON result of this group of data
Normal serializer deserialization creation
The concept of deserialization is very simple, which is to change JSON and other data into ORM data objects, or even warehousing or modification**
DRF requires that the serializer must verify the data in order to obtain the successfully verified data or save it as a model class object
- During the operation, deserialization first needs to pass parameters through data
- Then call is_valid for verification. If the verification is successful, it returns True. Otherwise, it returns False**
- If the verification fails, you can also return an error value through the errors property of the result
- ***is_valid * after calling, the method will verify the field attribute (max_value=10) * *, user-defined verification, etc
- Call the * * * save * * * method on the verified object. This * * save method will trigger the * * * create * * * method in the serializer
- In ordinary serializers, the * * * create * * * method is not implemented by default and needs to be written manually according to the model class
data = { 'name':"Zhang San", ... } ser = Serializer(data=data) if ser.is_valid(): ser.save() # When only the data parameter is passed, the save method will trigger the create method in the serializer
For example, you can do this now or in the previous exercise when you need to submit data to create an interface for the course
In order to ensure the successful warehousing of data, the default ordinary serializer does not have the warehousing function, and the * * * create * * * method needs to be written
class CourseSer(serializers.Serializer): name = serializers.CharField(max_length=20) created = serializers.DateField() def create(self, validated_data): object = Course.objects.create( **validated_data ) return object
After success, you can complete the data warehousing by submitting the data and writing the view as before. The serializer can directly process the data submitted by * * * request * * * * * * data * * *, and can eliminate other redundant fields in * * request.data, only the fields in the serializer
class CourseCreate(APIView): def post(self, request): ser = CourseSer(data=request.data) if ser.is_valid(): ser.save() error = ser.errors return Response({'msg': error if error else 'success'})
Normal serializer deserialization update
Deserialization of verified data can not only create data, but also update data
- Update first requires an existing data, so you need to pass an existing ORM object through the * * instance parameter
- If a new value to be updated is required, the * * * data * * * parameter needs to be passed
- After that, you also need * * * is_ The valid * * * method is called to check whether the incoming data to be updated is legal
- Finally, * * * save * * * triggers the * * * update * * * method in the serializer
The default ordinary serializer does not have its own update method for data. Now you need to create a * * * update * * * method in the serializer
class CourseSer(serializers.Serializer): name = serializers.CharField(max_length=20) created = serializers.DateField() def update(self, instance, validated_data): # instance data to be updated, validated_data is new data instance.name = validated_data.get('name', instance.name) instance.type = validated_data.get('create', instance.type) instance.save() return instance
Then pass the ID of the data to be updated and the updated value through PUT to update a piece of data
class CourseUpdate(APIView): def put(self, request): id_ = request.data.get("id") # Gets the ID of the current update data try: course = Course.objects.get(pk=id_) except Course.DoesNotExist: return Response({'msg': 'Update failed,This data does not exist'}) ser = CourseSer(instance=course, data=request.data) if ser.is_valid(): ser.save() error = ser.errors return Response({'msg': error if error else 'success'})
Model serializer
Model serializer writing method
In the previous serializer, it is obvious that if there are fewer model class fields, it is OK, but there are more and more model fields, the developers need to reproduce more and more fields in the serializer, which is very troublesome
In addition, you have to manually implement * * * update * * * and * * create methods, and you can't just write serializer fields. You also have to have field properties
Therefore, with the current serializer associated with the model class, it is more convenient to map fields and write built-in methods. It is great 👍
The model class association serializer has the following three characteristics and one disadvantage
- characteristic
- Automatically generate a series of fields based on the model class
- Automatically generated series fields, including * * * unique * * *, * * * max_ Verification of length * * * and other attributes
- Contains the default implementation of * * * create * * * and * * * update * * *
- shortcoming
- The default property of the model class field is not automatically mapped
So what is the serializer associated with the model class? The new serializer base class is used
from rest_framework.serializers import ModelSerializer
For example, a commodity model class
class Goods(models.Model): title = models.CharField(max_length=200, verbose_name='Product title') description = models.TextField(verbose_name='describe') inventory = models.IntegerField(default=0, verbose_name='Inventory') price = models.DecimalField( max_digits=10, decimal_places=2, verbose_name='commodity price') cover = models.CharField(max_length=200, verbose_name='Cover picture') issale = models.BooleanField(default=False, verbose_name='Promotion') saleprice = models.DecimalField( max_digits=10, decimal_places=2, verbose_name='Promotion price') ishow = models.BooleanField(default=True,verbose_name='Is it on the shelf') createtime = models.DateTimeField(auto_now_add=True, verbose_name='Creation time') def __str__(self): return self.title class Meta: db_table = 'goods'
According to the previous normal serialization writing method, you need to synchronize a field and remember to synchronize the field properties, which is very troublesome
But it's easy to use the serializer associated with the model class
- First, inherit * * * ModelSerializer * * * base class
- Associate the model class through the * * model attribute in the serializer metaclass attribute
- The fields that the serializer needs to process are indicated by the fields property in the serializer metaclass property**
class GoodsSer(serializers.ModelSerializer): class Meta: model = Goods fields = '__all__' # Indicates all model class fields # exclude = ('createtime',) # Excluded fields # read_only_fields = ('title','description') # Fields for serialization only # fields = ('title','description','inventory') # Manually specify fields # extra_kwargs = { # 'price':{'min_value':0, 'required':True}, # } # Modify the option parameters of the original field
The serializer associated with the model class uses the same method as an ordinary serializer
Use the serializer to return all the current commodity data, or just pass in the * * instance parameter as before. Remember that since it is multiple commodities and not separate data, remember to add the many=True parameter
Model serializer deserialization creation and update
The creation of the model serializer is simpler. There is no need to manually implement the * * * create * * * method. The general process is as follows:
- Bind data for serializer, ser=Serializer(data=request.data)
- Check data, ser.is_valid()
- Storage and warehousing, ser.save()
Create commodity interface
class GoodsCreate(APIView): def post(self, request): ser = GoodsSer(data=request.data) if ser.is_valid(): ser.save() error = ser.errors return Response({'msg': error if error else 'success'})
Note: the field attribute generated automatically by deserialization will not contain the * * * default * * * field attribute in the original model class field
When updating a product data, the model serializer also comes with its own * * * update * * * method
Finer commodity interface
class GoodsUpdate(APIView): def put(self, request): id_ = request.data.get("id") try: goods = Goods.objects.get(pk=id_) except Goods.DoesNotExist: return Response({'msg': 'Update failed,This data does not exist'}) ser = GoodsSer(instance=goods, data=request.data) if ser.is_valid(): ser.save() error = ser.errors return Response({'msg': error if error else 'success'})
Comparison between model serializer and ordinary serializer
- When serializing, pass the model class object into the * * * instance * * * parameter
- The serialization result is obtained using the data attribute of the serializer object
- When deserialization is created, the data to be deserialized is passed into the data parameter
- For deserialization, remember to use * * * is first_ Valid * * * verification
- During deserialization update, the data object to be updated is passed into * * instance parameter, and the updated data is passed into data parameter
- The model serializer is more convenient than ordinary serializers, automatically generating serialization mapping fields, * * * create * * * methods, etc
- Associated foreign key serialization. Remember to add * * * many=True when there are many foreign keys in the field property***