Use of day91-day92-DjangoRestFrameWork serialization & deserialization

Use of day91-day92-DjangoRestFrameWork serialization & deserialization

1. Install DjangoRestFrameWork

pip install...

2. Register APP in settings

3. Add at the bottom of the settings, depending on whether you need to add the actual error, you can Baidu

REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": []
}

4. Use of DjangoRestFrameWork

1. Create a new serializers.py file under the APP

2. The first edition (initial edition)

2.1 The code of models.py is as follows (comparative reference)

from django.db import models

class Book(models.Model):
    title = models.CharField(max_length=32)
    CHOICES = ((1,'Python'), (2,'Linux'), (3,'GoLang'))
    category = models.IntegerField(choices=CHOICES)
    pub_time = models.DateField()
    publisher = models.ForeignKey(to='Publisher', on_delete=models.DO_NOTHING, null=True) # The foreign key of the book points to the publisher
    authors = models.ManyToManyField(to='Author') # Many-to-many books point to authors 
    
class Publisher(models.Model):
    publisher_name = models.CharField(max_length=32)

class Author(models.Model):
    author_name = models.CharField(max_length=32)

2.2 The code of serializers.py is as follows

2.2.1 from rest_framework import serializers

2.2.2 Inherit serializers.Serializer

2.2.3 The field name of the serialization class and the field name of models must be the same, but models.xxx becomes serializers.xxx,

You can define error_messages or required, similar to form

2.2.4 Note that the CHOICE field in models becomes CharField. Specify the source parameter. The parameter follows the ORM operation.

The main attention here is the use of the "get_CHOICE field name_display" method

2.2.5 Primary foreign key relationship: the main table field name = foreign key class (), pay attention to specify the many=True parameter in the many-to-many relationship

2.2.6 - required=False only serialization without verification - read_only=True only for serialization - write_only=True only for deserialization

2.2.7 Field names can be customized, custom fields are generally only used for deserialization

2.2.8 To create data, rewrite the create() method, and update data to rewrite the update() method. The function is the ORM operation

2.2.9 - Customizable validation function my_validate(), with the highest weight, the first validation, the validation function can be multiple,

Pay attention to specify validators=[my_validate,] in the serialization field, and add the validation function to the parameter list

- The verification function for a single serialized field, the weight is second, the second check, validate_field name()

- Perform joint verification on the deserialized fields, with the third weight and the third check, validate()

from rest_framework import serializers
from DjangoDemo import models
from rest_framework.exceptions import ValidationError


class PublisherSerializer(serializers.Serializer):
    id = serializers.IntegerField()
    publisher_name = serializers.CharField(max_length=32)

class AuthorSerializer(serializers.Serializer):
    id = serializers.IntegerField()
    name = serializers.CharField(max_length=32)


# Define your own field deserialization checker
# Check order first
def my_validate(value):
    if'python' in value.lower():
        return raise ValidationError({'title':'Title contains sensitive words'})
    return value

# Book main class
class BookSerializer(serializers.Serializer):
    id = serializers.IntegerField(required=False)
    title = serializers.CharField(max_length=32, validators=[my_validate, ]) # Specify validator
    "It's no longer InterField, change CHOICE to CharFiled, and specify source to follow ORM operation"
    "get_field_display, directly get the value behind choice"
    category = serializers.CharField(
        source='get_category_display', 
        read_only=True, 
        error_messages={'required':'Category cannot be empty'}
    )

    "Define a new deserialization field to distinguish it from category, write_only"
    post_category_id = serializers.IntegerField(write_only=True)
    pub_time = serializers.DateField(
        error_messages={'required':'Publication time cannot be empty','invalid':'Time format error'}
    )

    "Foreign Key"
    "Only get read-only serialization for this publisher and author"
    publisher = PublisherSerializer(read_only=True)
    "Foreign keys, many-to-many between books and authors"
    authors = AuthorSerializer(many=True, read_only=True)

    "The definition id is only written, and the deserialization field must be the same as the transmission field!"
    publisher_id = serializers.IntegerField(write_only=True)
    author_list = serializers.ListField(write_only=True)

    ############################################## #########################

    # To create data, you need to rewrite the create method
    def create(self, validated_data):
        "validated_data is the data after verification"
        "Prepare to perform ORM operations on verified data"
        created_book_obj = models.Book.objects.create(
            title=validated_data['title'],
            pub_time=validated_data['pub_time'],
            category=validated_data['post_category_id'],
            publisher_id=validated_data['publisher_id']
        )
        created_book_obj.authors.add(*validated_data['author_list'])

        "The object is not really created until the return is complete"
        return created_book_obj

    # Update data needs to rewrite the update method
    def update(self, instance, validated_data):
        "validated_data is the data after verification"
        instance.title = validated_data.get('title', instance.title)
        instance.pub_time = validated_data.get('pub_time', instance.pub_time)
        instance.category = validated_data.get('post_category_id', instance.category)
        instance.publisher_id = validated_data.get('publisher_id', instance.publisher_id)
        if validated_data.get('author_list'):
            instance.authors.set(validated_data.get('author_list'))
        instance.save()

        return instance
        
    ############################################## ##########################

    # Fixed usage, validate_XXX, which means to verify the field
    # Check order second
    @staticmethod
    def validate_title(value):
        if'python' in value.lower():
            raise ValidationError({'title':'Contains sensitive keywords'})
        return value

    # Use this method to perform joint verification on deserialized fields
    # attrs represents all the fields passed in
    # Check order third
    def validate(self, attrs):
        author_list = attrs.get('author_list')
        if verification of author_list fails:
            raise ValidationError({'authors':'The author does not exist'})
        return attrs

3. 2.Edition (Final Edition)

3.1 inherit serializers.ModelSerializer

3.2 The use of custom fields + serializers.SerializerMethodField() method fields, generally custom parameter display specifies read_only=True

3.3 get_XXX custom field name, the return value of the function will be returned to the custom field

3.4 obj is every table object serialized

3.5 Pay attention to the parameter setting model, fields, exclude, extra_kwargs in class Meta

3.6 Here you can also write a single field checksum joint check, validate_ field name (), check a single field, validate (), for deserialized fields

For joint verification, the same single field verification weight is the highest, and the joint verification weight is the lowest

3.7 Define list_serializer_class in class Meta when batch update

class BookSerializer(serializers.ModelSerializer):
    # Specify the method field, you can customize the rewrite of the field
    category_info = serializers.SerializerMethodField(read_only=True)
    publisher_info = serializers.SerializerMethodField(read_only=True)
    authors_info = serializers.SerializerMethodField(read_only=True)

    # obj is every Book object serialized
    # get_XXX Custom field name, the return value of the function will be returned to the custom field
    @staticmethod
    def get_category_info(obj):
        return obj.get_category_display()

    @staticmethod
    def get_publisher_info(obj):
        publisher_obj = obj.publisher
        return {'id': publisher_obj.id,'publisher_name': publisher_obj.publisher_name}

    @staticmethod
    def get_authors_info(obj):
        # Get all author objects, list comprehension
        authors_queryset = obj.authors.all()
        return [{'id': author.id,'author\'s name': author.name} for author in authors_queryset]
    
    # Verify the title field
    @staticmethod
    def validate_title(value):
        if'python' in value.lower():
            raise ValidationError({'title':'Contains sensitive keywords'})
        return value

    # Use this method to perform joint verification on deserialized fields
    def validate(self, attrs):
        author_list = attrs.get('author_list')
        if verification of author_list fails:
            raise ValidationError({'authors':'The author does not exist'})
        return attrs

    class Meta:
        # Used to update multiple data
        class MultiUpdateSerializer(serializers.ListSerializer):
            def update(self, instance, validated_data):
                # The instance here represents the object model list, validated_data is the data list
                # child represents each update object
                # The update called by child is the object of each BookSerializer
                return [self.child.update(instance[i], validated_data[i]) for i in range(len(validated_data))]

        # When there are multiple updates
        list_serializer_class = MultiUpdateSerializer
        model = models.Book
        # This represents all the fields of this table are obtained by default
        fields ='__all__'

        # exclude=['id']

        # Set this field to write-only, the parameters of this field will not be passed to the front end
        extra_kwargs = {
            'title': {
                'write_only': True,
                'min_length': 2,
                'error_messages': {
                    'min_length':'The minimum length of the title cannot be less than 2',
                }
            },

            'publisher': {
                'write_only': True,
                'required': True,
                'error_messages': {
                    'required':'The publisher id cannot be empty',
                    'incorrect_type':'Incorrect publisher format' # Foreign key type
                    'does_not_exist':'A publishing house that does not exist'
                }
            },

            'pub_time': {'error_messages': {
                'invalid':'The parameter type is invalid'
            }},

            'authors': {
                'write_only': True,
                'error_messages': {
                    'required':'The author field cannot be empty',
                    'not_a_list':'Illegal author sequence', # list type
                    'does_not_exist':'Does not exist author',
                }
            },

            'category': {
                'write_only': True,

            },
        }

4.视图中

4.0 from rest_framework.views import APIView, Response

4.1 from SerDemo.serializers import BookSerializer, import your own serializer

4.2 The class here inherits APIView, not View

4.3 What is returned here is Response, not HTTPResponse

4.4 Know that the parameters passed by the interface are in request.data

4.5 Get request directly transfer queryset, post request is data=XXX

4.6 Whether it is a queryset or a single obj, or the request.data of the interface, it must be entered into XxxSerializers

4.7 When sending queryset, pay attention to specify many=True parameter

4.8 Pay attention to save

4.9 Successfully return ser_obj.data

from rest_framework.views import APIView
from rest_framework.response import Response
from .serializers import BookSerializer
from. import models
from rest_framework.request import Request

class TestView(APIView):
    @classmethod
    def get(cls, request: Request):
        """Inquire"""
        book_queryset = models.Book.objects.all()
        ser_obj = BookSerializer(book_queryset, many=True)
        return Response(ser_obj.data)

    @classmethod
    def post(cls, request: Request):
        """Add"""
        book_obj = request.data
        ser_obj = BookSerializer(data=book_obj, many=True)
        if ser_obj.is_valid():
            ser_obj.save()
            return Response(ser_obj.data)
        return Response(ser_obj.errors)

    @classmethod
    def put(cls, request: Request):
        """modify"""
        """The comment part is a single modification"""
        # book_obj = models.Book.objects.filter(id=request.data.get('id')).first()
        # ser_obj = BookSerializer(instance=book_obj, data=request.data)
        # print('Whether the verification passed-->', ser_obj.is_valid())
        # if ser_obj.is_valid():
        # ser_obj.save()
        # return Response(ser_obj.data)
        # return Response(ser_obj.errors)

        update_list = request.data
        book_model_list = [
            models.Book.objects.filter(id=item['id']).first() for item in update_list
        ]
        ser_obj = BookSerializer(instance=book_model_list, data=request.data, many=True)
        if ser_obj.is_valid():
            ser_obj.save()
            return Response(ser_obj.data)
        return Response(ser_obj.errors)

    @classmethod
    def delete(cls, request: Request):
        """delete"""
        id_list = request.data.get('id_list')
        delete_queryset = models.Book.objects.filter(id__in=id_list)
        if delete_queryset.count() != len(id_list):
            return Response('non-existent id')
        delete_queryset.delete()
        return Response('Operation successful')

 # Data structure post or delete, post does not need to pass id
 [
    {
        "id":35,
        "title": "日bbbb",
        "category": 1,
        "pub_time": "2020-02-29",
        "publisher": 2,
        "authors": [1,2]
    }
]
Reference: https://cloud.tencent.com/developer/article/1592539 day91-day92-DjangoRestFrameWork serialization & deserialization use-cloud + community-Tencent Cloud