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

 

 

 

 

 

 

posted @ 2018-08-03 22:10  YaoSir66  阅读(108)  评论(0编辑  收藏  举报