zoukankan      html  css  js  c++  java
  • Django的rest_framework的序列化组件之serializers.ModelSerializer介绍

    这里的介绍的serializers.ModelSerializer就和我们之前学习的modelform一样

    serializers.ModelSerializer如下几个功能

    1、序列化queryset数据

    2、反序列化json数据,将反序列化后的数据转换成model对象

    3、反序列化的时候还是可以对数据做校验

    4、如果合法,可以调用sava方法进行post或者put请求操作

    5、如果不合法,则返回错误

    下面我们进入serializers.ModelSerializer的学习

    首先写一个modelserializer的类,不知道看官有没有发现,和我们之前学的modelform几乎完全一样

    class bookmodelserializer(serializers.ModelSerializer):
        class Meta:
            model = models.Book
            fields = "__all__"
    

      

    然后我们在get请求中,如何通过上面的类序列化queryset对象,可以看到直接之前的serializer类替换为modelserializer类就可以了

    from rest_framework.views import APIView
    from rest_framework.response import Response
    class Book_cbv(APIView):
        def get(self,request):
            query_list = models.Book.objects.all()
            # bs = book_serializers(query_list,many=True)
            bs = bookmodelserializer(query_list,many=True)
    
            print(dir(serializers))
            return Response(bs.data)
    

      

    通过postman发送get请求,我们看下受到的信息,我们看到一对多字段和多对多字段均为所对应对象的id,我们可以定制化的显示我们需要显示的信息,但是这里暂时不做讲解,在博客的后面我们在做讲解

     上面处理完了get请求,下面我们在处理一下post请求,我们通过postman发送json信息,然后通过modelserializerlizer直接保存信息,post请求处理的代码如下

    如何数据有效,则保存数据,这个也和modelform非常的类型,可以说是完全一样

        def post(self,request):
            bs = bookmodelserializer(data=request.data)
    
            if bs.is_valid():
                print(bs.validated_data)
                bs.save()
                return Response(bs.data)
            else:
                return Response(bs.errors)
    

     

    下面我们通过postman发送post请求,测试一下

     

    发送完post请求,我们看下返回的结果,将我们的新增的数据返回了

     至此,modelserializar的基本用法我们就讲完了

    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    下面我们开始定制化的处理

    首先,在get请求中,对于一对多和多对多的字段,我们想定制化的显示,那么我们就可以这样做

    class bookmodelserializer(serializers.ModelSerializer):
        class Meta:
            model = models.Book
            fields = "__all__"
        # 一对多,关联指定的对象,然后显示指定对象的字段
    
    
        book_publish = serializers.CharField(source="book_publish.id")
    
        book_auther = serializers.SerializerMethodField()
        def get_book_auther(self,obj):
    
            s = ""
            for i in obj.book_auther.all():
                s = s + i.auther_name + "|"
    
            s = s.rstrip("|")
            return s
    

      

    重点是这里,就是serializer中处理一对多和多对多的代码拿过来就可以了

     下面我们通过postman发送get请求,看下前端的显示效果,看到效果,已经实现了我们的想要的结果

     上面解决了定制化的处理get请求,那么post请求行不行呢?

    我们直接使用postman来做一下测试

     我们看到有报错,其实的modelserializer这个类的create方法无法处理这种定制的话的数据

    下面的是modelserializer类的create方法

        def create(self, validated_data):
            """
            We have a bit of extra checking around this in order to provide
            descriptive messages when something goes wrong, but this method is
            essentially just:
    
                return ExampleModel.objects.create(**validated_data)
    
            If there are many to many fields present on the instance then they
            cannot be set until the model is instantiated, in which case the
            implementation is like so:
    
                example_relationship = validated_data.pop('example_relationship')
                instance = ExampleModel.objects.create(**validated_data)
                instance.example_relationship = example_relationship
                return instance
    
            The default implementation also does not handle nested relationships.
            If you want to support writable nested relationships you'll need
            to write an explicit `.create()` method.
            """
            raise_errors_on_nested_writes('create', self, validated_data)
    
            ModelClass = self.Meta.model
    
            # Remove many-to-many relationships from validated_data.
            # They are not valid arguments to the default `.create()` method,
            # as they require that the instance has already been saved.
            info = model_meta.get_field_info(ModelClass)
            many_to_many = {}
            for field_name, relation_info in info.relations.items():
                if relation_info.to_many and (field_name in validated_data):
                    many_to_many[field_name] = validated_data.pop(field_name)
    
            try:
                instance = ModelClass._default_manager.create(**validated_data)
            except TypeError:
                tb = traceback.format_exc()
                msg = (
                    'Got a `TypeError` when calling `%s.%s.create()`. '
                    'This may be because you have a writable field on the '
                    'serializer class that is not a valid argument to '
                    '`%s.%s.create()`. You may need to make the field '
                    'read-only, or override the %s.create() method to handle '
                    'this correctly.
    Original exception was:
     %s' %
                    (
                        ModelClass.__name__,
                        ModelClass._default_manager.name,
                        ModelClass.__name__,
                        ModelClass._default_manager.name,
                        self.__class__.__name__,
                        tb
                    )
                )
                raise TypeError(msg)
    
            # Save many-to-many relationships after the instance is created.
            if many_to_many:
                for field_name, value in many_to_many.items():
                    field = getattr(instance, field_name)
                    field.set(value)
    
            return instance
    

      

    因为我们的对象是继承了modelserializer类,所以我们重写一下create方法,就可以解决这个问题,因为如果我们的类中有create方法,会优先调用我们自己的create方法,只有当我们的类中没有create方法,才会去调用父类的create方法

    首先我们在自己的类中定义一个create方法,先打印参数看看

    class bookmodelserializer(serializers.ModelSerializer):
        class Meta:
            model = models.Book
            fields = "__all__"
        # 一对多,关联指定的对象,然后显示指定对象的字段
        def create(self, validated_data):
            print(validated_data)
    
        book_publish = serializers.CharField(source="book_publish.id")
    
        book_auther = serializers.SerializerMethodField()
        def get_book_auther(self,obj):
    
            s = ""
            for i in obj.book_auther.all():
                s = s + i.auther_name + "|"
    
            s = s.rstrip("|")
            return s
    

      

    create方法我们下截图出来

     我们再次通过postman发送post请求,看下打印的结果

    这里我无论如何怎么处理,在新的create方法中均无法打印出book_auther的数据,我也是很纳闷

    无论我在上面的函数中返回一个字符串,还是一个list,都不行

    上面这一行是reqeust.data中的数据,下面这一行是validated_data中的数据

     那么我暂时把多对多中的定制化处理注销掉,用默认的方式显示把

    class bookmodelserializer(serializers.ModelSerializer):
        class Meta:
            model = models.Book
            fields = "__all__"
        # 一对多,关联指定的对象,然后显示指定对象的字段
        def create(self, validated_data):
            print("validated_data",validated_data)
            # models.Book.objects.create(
            #     book_name = validated_data
            # )
        book_publish = serializers.CharField(source="book_publish.id")
    
        # book_auther = serializers.SerializerMethodField()
        # def get_book_auther(self,obj):
        # 
        #     s = []
        #     for i in obj.book_auther.all():
        #         s.append(i)
        # 
        # 
        #     return s
    

      

    这次我们通过postman发送post请求

    这次validated_data中就有book_auther信息就了

     

    然后我们调用create方法在数据库中创建数据就可以了

    class bookmodelserializer(serializers.ModelSerializer):
        class Meta:
            model = models.Book
            fields = "__all__"
        # 一对多,关联指定的对象,然后显示指定对象的字段
        def create(self, validated_data):
            print("validated_data",validated_data)
            ret = models.Book.objects.create(
                book_name = validated_data["book_name"],
                book_price = validated_data["book_price"],
                book_publish_id = validated_data["book_publish"]["id"]
            )
            ret.book_auther.add(*validated_data["book_auther"])
    
            return ret
    

      

    这个时候我们在通过postman发送post请求,可以看到创建数据成功了

     至于定制化的多对多字段,我下来在研究一下,今天太晚了,明天还得上班!

    
    
    
  • 相关阅读:
    关于汉密尔顿回路
    hdu 3018 Ant Trip
    hdu 1116 Play on Words
    关于欧拉回路、欧拉通路的一些定理及推论
    hdu 1531 King
    hdu 3440 House Man
    hdu 3666 THE MATRIX PROBLEM
    hdu 1384 Intervals
    关于差分约束系统
    hdu 1878 欧拉回路
  • 原文地址:https://www.cnblogs.com/bainianminguo/p/10448013.html
Copyright © 2011-2022 走看看