使用DjangoRestframework序列化器重写get方法及源码分析

查询接口的重新写法

新建一个子应用

python manage.py startapp book_drf, 把这个子应用在父应用的setting.py里进行注册,然后父应用的urls.py的新加路由,指定到子应用的路由中,在子应用urls.py中添加路由,指向子应用中的视图views.py中的类名。

from django.contrib import admin
from django.urls import path, include
from django.conf.urls import url

urlpatterns = [
    path('admin/', admin.site.urls),
    url('projects/', include('testdjango.urls')),
    url('projects/', include('book_drf.urls')),
]
from django.urls import path
from django.conf.urls import url
from book_drf import views

urlpatterns = [
    url(r'^book_drf/$', views.Books.as_view()),
    url(r'^book_drf/(?P<pk>\d+)/$', views.Book.as_view()),
]

在新的子应用的视图(views)中先导入使用django的视图

需要创建一个序列化器,serializer.py,需要返回哪些字段就写哪些字段,字段的类型与models里的类型一致

from rest_framework import serializers


# 自定义序列化器,本质就是一个类
class BookSerializer(serializers.Serializer):

    # 序列化返回的字段
    btitle = serializers.CharField()
    bpub_date = serializers.DateField()
    bcomment = serializers.IntegerField()

在view.py中重写get方法,对象数据转成json数据,直接使用序列化器,多个对象返回的时候需要加many=True。序列化后也是一个对象,这个对象里的data就是序列化后的内容。返回单个对象的时候不需要many=True

from django.shortcuts import render
from django.views import View
from testdjango.models import BookInfo
from book_drf.serializer import BookSerializer
from django.http import JsonResponse


class Books(View):

    def get(self, request):
        books = BookInfo.objects.all()
        # 多个对象返回的时候需要加上many=True
        ser = BookSerializer(books, many=True)
        return JsonResponse(ser.data, safe=False)


class Book(View):

    def get(self, request, pk):
        book = BookInfo.objects.get(id=pk)
        ser = BookSerializer(book)
        return JsonResponse(ser.data)

http://127.0.0.1:8000/projects/book_drf/

 http://127.0.0.1:8000/projects/book_drf/1/

 序列化器的使用,可以看出,这个序列化器类里有个data方法,但是BookSerializer中并没有定义这个data方法。但是它继承了serializers.Serializer。

        ser = BookSerializer(books)
        return JsonResponse(ser.data)

点Serializer查看源码,查找里面存在一个data()方法

 可以看出这个data方法就是返回的一个字典类型的数据,但是调用这个方法的时候类名没有使用括号,ser.data。这是因为这个data方法上面有一个@property装饰器,把方法当做属性进行使用。所有可以直接使用类名+“.” 的形式使用。

可以看到这个方法其实有使用它的父类里data(),点进去看下,里面有个self.instance这个属性就是接收的我们传的对象

 当我们使用序列化的时候是传了一个对象数据给序列化器的,

 ser = BookSerializer(books)

 在这个父类中BaseSerializer 可以找到初始化方法,打个断点进行验证。instance接收完对象后,赋值给self.instance,整个类里面都可以使用这个instance属性

 然后接着回来看data()方法,data方法进行判断self.instance是否为空,不为空后,调用self.to_representation这个方法。把self.instance的值,也就是对象数据,当做入参传递进来


        if not hasattr(self, '_data'):
            if self.instance is not None and not getattr(self, '_errors', None):
                self._data = self.to_representation(self.instance)
            elif hasattr(self, '_validated_data') and not getattr(self, '_errors', None):
                self._data = self.to_representation(self.validated_data)
            else:
                self._data = self.get_initial()
        return self._data

点进去self.to_representation 看下这个方法,是看这个方法是不是必须的字段内容

总结来说就是我们的数据对象是被 父类BaseSerializer中的instance属性接收了。还有使用的时候

ser.data的时候,这个data不是属性,其实一个方法,只是用了@property装饰器,把它当做属性使用。data方法是把数据对象提取出来转化为字典,再转化为json格式的数据。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

NeilNiu

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

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

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

打赏作者

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

抵扣说明:

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

余额充值