Django的rest_framework的serializers.ModelSerializer介绍

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

serializers.ModelSerializer也有两个功能

1、序列化queryset数据

2、反序列化json数据,将反序列化后的数据转换成model对象,直接写到数据库中

下面我们进入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,我们可以定制化的显示我们需要显示的信息,但是这里暂时不做讲解,在博客的后面我们在做讲解

扫描二维码关注公众号,回复: 5349615 查看本文章

 上面处理完了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.\nOriginal exception was:\n %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请求,可以看到创建数据成功了

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

 

猜你喜欢

转载自www.cnblogs.com/bainianminguo/p/10448013.html
今日推荐