DRF的序列化组件
rest
rest下的url
url唯一代表资源,http请求方式来区分用户行为
url的设计规范
GET: 127.0.0.1:9001/books/ # 获取所有数据
GET: 127.0.0.1:9001/books/{id} # 获取单条数据
POST: 127.0.0.1:9001/books/ # 增加数据
DELETE: 127.0.0.1:9001/books/{id} # 删除数据
PUT: 127.0.0.1:9001/books/{id} # 修改数据
数据响应规范
GET: 127.0.0.1:9001/books/ # 返回[{}, {}, {}]
GET: 127.0.0.1:9001/books/{id} # {} 单条数据
POST: 127.0.0.1:9001/books/ # {} 添加成功的数据
DELETE: 127.0.0.1:9001/books/{id} # "" 返回空
PUT: 127.0.0.1:9001/books/{id} # {} 更新后完整的数据
错误处理
{ "error": "message" }
解析器组件
解析器组件是用来解析用户请求的数据的(application/json), content-type
必须继承APIView
request.data触发解析
APIView的使用
rest_framework是一个app需要在settings里设置
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'rest_framework', ]
pip install djangorestframework
from rest_framework.views import APIView
class LoginView(APIView):
def get(self, request):
pass
序列化组件
Django自带的serializer
from django.serializers import serialize # 引入 origin_data = Book.objects.all() serialized_data = serialize("json", origin_data)
DRF的序列化组件
接口设计
from rest_framework import serializers #引入
创建一个序列化类
class BookSerializer(serializers.ModelSerializer): class Meta: model = Book # model字段 fields = ('title', 'price', 'publish', 'authors', 'author_list', 'publish_name', 'publish_city' ) # 只需写入不需要展示的字段 extra_kwargs = { 'publish': {'write_only': True}, 'authors': {'write_only': True} } # source为自定义需要展示的信息 publish_name = serializers.CharField(max_length=32, read_only=True, source='publish.name') publish_city = serializers.CharField(max_length=32, read_only=True, source='publish.city') # 多对多字段需要自己手动获取数据,SerializerMethodField() author_list = serializers.SerializerMethodField() def get_author_list(self, book_obj): # 拿到queryset开始循环 [{}, {}, {}, {}] authors = list() for author in book_obj.authors.all(): authors.append(author.name) return authors
开始序列化
get接口(查询多条数据) & post接口
class BookView(APIView): def get(self, request): # 获取queryset origin_data = Book.objects.all() # 开始序列化 serialized_data = BookSerializer(origin_data, many=True) return Response(serialized_data.data) def post(self, request): verified_data = BookSerializer(data=request.data) if verified_data.is_valid(): book = verified_data.save() authors = Author.objects.filter(nid__in=request.data['authors']) book.authors.add(*authors) return Response(verified_data.data) else: return Response(verified_data.errors)
get(查询单条数据) & put接口 & delete接口
class BookFilterView(APIView): def get(self, request, nid): book_obj = Book.objects.get(pk=nid) serialized_data = BookSerializer(book_obj, many=False) return Response(serialized_data.data) def put(self, request, nid): book_obj = Book.objects.get(pk=nid) verified_data = BookSerializer(data=request.data, instance=book_obj) if verified_data.is_valid(): verified_data.save() return Response(verified_data.data) else: return Response(verified_data.errors) def delete(self, request, nid): book_obj = Book.objects.get(pk=nid).delete() return Response()
缺点:
serializers.Serializer无法插入数据,只能自己实现create字段太多,不能自动序列化
接口设计优化
使用视图组件的mixin进行接口逻辑优化
导入mixin
from rest_framework.mixinx import ( ListModelMix, CreateModelMixin, DestroyModelMixin, UpdateModelMixin, RetrieveModelMixin ) from rest_framework.generics import GenericAPIView
定义序列化类
Class BookSerializer(serializers.ModelSerializer): class Meta: Book fields = () ...如上
因为使用模块化编程,建议将定义的序列化类放在单独的模块中,再在view.py中导入
from .app_serializers import BookSerializer
定义视图类
class BookView(ListModelMix, CreateModelMixin, GenericAPIView): # queryset和serializer_class是固定的写法 queryset = Book.objects.all() serializer_class = BookSerializer def get(): return self.list() # 查询多条 def post(): return self.create() class BookFilterView(RetrieveModelMixin, DestroyModelMixin, UpdateModelMixin, GenericAPIView): queryset = Book.objects.all() serializer_class = BookSerializer def get(): return self.retrieve() # 查询单条 def delete(): return self.destroy() def put(): return self.update()
注意:
查询单挑数据的url需要给查询的id进行正则分组
re_path(r'books/(?P<pk>\d+)/$, views.BookFilterView.as_view())
使用视图组件的view进行接口逻辑优化
导入模块
from rest_framework import generics
视图类
class BookView(generics.ListCreateAPIView) queryset = Book.objects.all() serializer_class = BookSerializer class BookFilterView(generics.RetrieveUpdateDestroyAPIView): queryset = Book.objects.all() serializer_class = BookSerializer
使用视图组件的viewset进行接口逻辑优化
导入模块
from rest_framework.viewsets import ModelViewSet
设计url
re_path(r'books/$, views.BookView.as_view({ 'get': 'list', 'post': 'create' })), re_path(r'books/(?P<pk>\d+)/$', views.BookView.as_view({ 'get': 'retrieve', 'delete': 'destroy', 'put': 'update' }))
设计视图类
class BookView(ModelViewSet): queryset = Book.objects.all() serializer_class = BookSerializer