查询接口的重新写法
新建一个子应用
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格式的数据。