Django restframework重写get_serializer_class方法自定义serializer_class

1 篇文章 0 订阅
1 篇文章 0 订阅


活动地址:CSDN21天学习挑战赛

view承restframeworkgenerics.ListAPIView的接口后,需要定义serializer_class实现数据的序列化,但是往往我们写业务逻辑时不确定具体的序列化class,这时候据需要根据传递的参数或者路由(url)来动态配置serializer_class,那么如何动态配置序列化类serializer_class呢?

get_serializer_class(self)介绍

在restframework的GenericAPIView类有get_serializer_class(self)方法,调用get_serializer_class(self)方法时默认返回设置的serializer_class序列化类,只要在我们的view中重写get_serializer_class(self)方法即可实现动态配置serializer_class

get_serializer_class(self)源码如下:

def get_serializer_class(self):
    """
    Return the class to use for the serializer.
    Defaults to using `self.serializer_class`.

    You may want to override this if you need to provide different
    serializations depending on the incoming request.

    (Eg. admins get full serialization, others get basic serialization)
    """
    assert self.serializer_class is not None, (
        "'%s' should either include a `serializer_class` attribute, "
        "or override the `get_serializer_class()` method."
        % self.__class__.__name__
    )

    return self.serializer_class

官方文档: https://www.django-rest-framework.org/api-guide/generic-views/#get_serializer_classself

重写get_serializer_class(self)

重写get_serializer_class(self)方法实现动态配置序列化类,这里需要注意的是如果重写get_serializer_class(self)一定要返回一个序列化类,如果没有返回一个序列化类即使定义了serializer_class也会报错。

还有一个问题需要注意,当自定义序列化类后对应的model也需要根据自定义的序列化类改变,这样在调用self.get_serializer(page, many=True, request=request)方法后才可以正常序列化数据,但是如何动态获取model实现查询queryset呢?
这时候可以通过调用重写的get_serializer_class()方法获取序列化类,再根据序列化中的Meta类获取实体类model,然后实现数据查询。

完整的代码如下:

class Menus(generics.ListAPIView):
    renderer_classes = [TemplateHTMLRenderer]
    serializer_class = ArticlesSerializer  # 定义默认序列化类
    pagination_class = Pagination          # 定义翻页类(Pagination继承PageNumberPagination重写)
    
    # 重写get_serializer_class(self)实现动态配置serializer_class
    def get_serializer_class(self):
        menu = self.request.GET.get("menu")
        if menu == "categories":
            return CategoriesArticlesSerializer
        elif menu == "tags":
            return TagsArticlesSerializer
        else:
            return super().get_serializer_class()  # 获取父类的get_serializer_class(),也就serializer_class配置的序列化类

    def list(self, request):
        menu = request.GET.get("menu")
        Serializer = self.get_serializer_class()  # 获取序列化类
        model = Serializer.Meta.model             # 根据序列化类获取model
        queryset = model.objects.all()            # 查询数据queryset
        page = self.paginate_queryset(queryset)   # 获取分页数据queryset
        if page is not None:
            serializer = self.get_serializer(page, many=True, request=request)    # 实现数据序列化
            return self.get_paginated_response({'articles': serializer.data, "template_name": '%s.html' % menu})
        serializer = self.get_serializer(instance=queryset, many=True)
        return Response({"data": {'articles': serializer.data, template_name='%s.html' % menu)

小结

上面的代码中pagination_class = Pagination Pagination类是继承PageNumberPagination,重写了get_paginated_response方法,实现页码、总页码、上一页、下一页和总条数等计算和相关message、code信息,这里后面文章也会介绍。

还有此篇文章renderer_classes渲染器用的Django模板,调用了TemplateHTMLRenderer,通过定义template_name实现数据渲染的html,这里由于需要动态调用不同的html,所以把template_name放在了Response进行指定,但是这样不够优雅,可以通过重写get_template_names方法自定义模板界面,这里后面文章也会介绍。

最后通过在实现自定义序列化类,学习了djangorestframeworkGenericAPIView类源码,看到所有的restframework的apiview都继承了GenericAPIView类。djangorestframework提供了丰富的类视图、Mixin扩展类,简化视图的编写。此篇文档就到这里,后面会逐步对djangorestframework其他功能进行扩展介绍,包括序列化、反序列化、身份认证和权限认证等,敬请期待。

此篇文章如果对你有帮助,请点赞收藏加关注。如果有疑问可以评论留言哈。

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
Django REST Framework 中,处理一对多的连表查询和更新操作通常使用 Serializer 进行实现。 对于查询操作,可以使用 Serializer 中的嵌套序列化器来实现。例如,如果有一个 User 模型和一个 Post 模型,其中一个 User 可能有多个 Post。可以在 UserSerializer 中嵌套 PostSerializer 来序列化 User 模型及其相关的多个 Post 模型。 对于更新操作,可以使用 Serializer 中的 create() 和 update() 方法来实现。在 Serializer重写这些方法可以指定如何创建和更新相关模型的实例。 例如,如果要更新一个 User 模型及其关联的多个 Post 模型,可以在 UserSerializer重写 update() 方法,以便在一个请求中同时更新 User 和 Post 模型。 示例代码如下: ```python from rest_framework import serializers from myapp.models import User, Post class PostSerializer(serializers.ModelSerializer): class Meta: model = Post fields = '__all__' class UserSerializer(serializers.ModelSerializer): posts = PostSerializer(many=True, read_only=True) class Meta: model = User fields = '__all__' def update(self, instance, validated_data): posts_data = validated_data.pop('posts', []) instance = super().update(instance, validated_data) posts_serializer = self.fields['posts'] for post_data in posts_data: post_instance = instance.posts.filter(pk=post_data.get('id')).first() if post_instance: posts_serializer.update(post_instance, post_data) else: post_data['user'] = instance.id posts_serializer.create(post_data) return instance ``` 在上面的代码中,UserSerializer 中嵌套了 PostSerializer,通过设置 many=True 和 read_only=True 来指定 posts 是一个多对一的关系,并且只读。在 update() 方法中,首先处理 User 模型的更新,然后遍历 posts_data 中的数据,对每个 Post 模型进行更新或创建操作。如果 Post 模型已存在,则使用 PostSerializer 中的 update() 方法进行更新;否则,使用 create() 方法进行创建,并将 User 模型的 id 赋值给 post_data 中的 user 字段。最后返回更新后的 User 实例。 总之,使用 Serializer 可以方便地处理一对多的连表查询和更新操作。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我在那路边

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值