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
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

我在那路边

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

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

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

打赏作者

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

抵扣说明:

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

余额充值