随笔 - 331,  文章 - 92,  评论 - 54,  阅读 - 60万

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

serializers.ModelSerializer如下几个功能

1、序列化queryset数据

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

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

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

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

 

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

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

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

  

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

1
2
3
4
5
6
7
8
9
10
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非常的类型,可以说是完全一样

1
2
3
4
5
6
7
8
9
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请求中,对于一对多和多对多的字段,我们想定制化的显示,那么我们就可以这样做

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
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方法,先打印参数看看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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中的数据

 

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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方法在数据库中创建数据就可以了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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请求,可以看到创建数据成功了

 

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

 


 

posted on   bainianminguo  阅读(3729)  评论(1编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
历史上的今天:
2018-02-28 利用python计算windows全盘文件md5值的脚本

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示