Django的rest_framework的序列化組件之serializers.ModelSerializer介紹

這裏的介紹的serializers.ModelSerializer就和咱們以前學習的modelform同樣前端

serializers.ModelSerializer以下幾個功能python

一、序列化queryset數據數據庫

二、反序列化json數據,將反序列化後的數據轉換成model對象json

三、反序列化的時候仍是能夠對數據作校驗app

四、若是合法,能夠調用sava方法進行post或者put請求操做ide

五、若是不合法,則返回錯誤函數

 

下面咱們進入serializers.ModelSerializer的學習post

首先寫一個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.\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請求,能夠看到建立數據成功了

 

 至於定製化的多對多字段,我下來在研究一下,今天太晚了,明天還得上班!

相關文章
相關標籤/搜索