【DRF】Django REST FramkWork 学习笔记(更新中~)

2,708 阅读5分钟

前言

这篇文章是我从0到1学习 DRF 的学习笔记先把我觉得重要的和踩过的统一记录下来,后面会单独拆分成多篇针对性文章,有什么不足的,还请大家指正~


地址

DRF:www.django-rest-framework.org/
Django:docs.djangoproject.com/zh-hans/2.1…
项目源码:gitee.com/Actoress/dj…


Django 基础

拆分笔记:juejin.cn/post/684490…


Django REST FrameWork 基础

序列化器类

Serializer

1)如果定义的序列化器类不是针对于模型类,可以直接继承此类即可。
2)没有提供save时的create方法和update方法。

ModelSerializer

1)如果定义的序列化器类是针对于模型类,可以直接继承此类即可。
2)提供了save时的create方法和update方法。

1)序列化:

python创建序列化器对象并传入所有序列化的对象serializer = BookInfoSerializer(book)
获取序列化之后的字典数据serializer.data

2)反序列化-数据验证

python创建序列化器对象并传入数据 serializer = BookInfoSerializer(data=data)
调用is_valid方法进行数据验证 serializer.is_valid()

3)反序列化-新增或更新

a)新增

python 创建序列化器对象并传入数据 serializer = BookInfoSerializer(data=data) 调用is_valid方法进行数据验证 serializer.is_valid() 调用save方法时会调用序列化器类中的create方法,可以在create方法中实现数据的添加 serializer.save()

b)更新

python 创建序列化器对象并传入数据 serializer = BookInfoSerializer(book, data=data) 调用is_valid方法进行数据验证 serializer.is_valid() 调用save方法时会调用序列化器类中的update方法,可以在update方法中实现数据的添加 serializer.save()

路由Router

1.路由Router是专门配合视图集来使用的,可以使用Router自动生成视图集中相应处理函数对应的URL配置项。
2.使用Router自动生成视图集中相应处理函数对应的URL配置项时,除了常见的5种基本操作之外,如果视图集中有添加的其他处理方法,则需要给这些方法加上action装饰器之后,才会动态生成其对应的URL配置项。


Django REST FrameWork API

Django类视图(不推荐)

import json
from django.http.response import HttpResponse
from django.views.generic.base import View
from goods.models import Goods

class GoodsListView(View):
    def get(self, request):
        json_list = []
        goods = Goods.objects.all()[:10]
        for good in goods:
            json_dict = {}
            json_dict["name"] = good.name
            json_dict["category"] = good.category.name
            json_list.append(json_dict)
        renturn HttpResponse(json.dumps(json_list), content_type="application/json")
        
------------------------------------------------------------------------------------------
urlpatterns = [
    path('goods/', GoodsListView.as_view(), name="goods"),
]

Django类视图优化(不推荐)

"""【views.py】"""
import json
from django.http.response import JsonResponse
from django.views.generic.base import View
from django.core import serializers  # 做序列化
from goods.models import Goods

class GoodsListView(View):
    def get(self, request):
        json_list = []
        goods = Goods.objects.all()[:10]
        json_data = serializers("json", goods)  # 做序列化
        json_data = json.loads(json_data)
        return JsonResponse(json_data, safe=False)
        
------------------------------------------------------------------------------------------

"""【urls.py】"""
urlpatterns = [
    path('goods/', GoodsListView.as_view(), name="goods"),
]

Django Rest FrameWork APIView 视图(推荐)

"""【views.py】"""
from django.http import Http404
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status

from .models import Goods
from .serializers import GoodsSerializer

class GoodsListView(APIView):
    def get(self, request, format=None):
        goods = Goods.objects.all()[:10]
        serializer = GoodsSerializer(goods, many=True)  # many=True 表示是一个 list 对象
        return Response(serializer.data)

    def post(self, request, format=None):
        serializer = GoodsSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        
------------------------------------------------------------------------------------------

"""【serializers.py】"""
from rest_framework import serializers

from .models import Goods

class GoodsSerializer(serializers.Serializer):
    name = serializers.CharField(required=True, max_length=100)
    click_num = serializers.IntegerField(default=0)
    
    def create(self, validated_data):
        """
        重载create方法,当新建一条数据时,会调用这里的方法,验证数据
        """
        return Goods.objects.create(**validated_data)

    def update(self, instance, validated_data):
        """
        Update and return an existing `good` instance, given the validated data.
        """
        instance.title = validated_data.get('title', instance.title)
        instance.code = validated_data.get('code', instance.code)
        instance.save()
        return instance
        
------------------------------------------------------------------------------------------

"""【urls.py】"""
urlpatterns = [
    path('goods/', GoodsListView.as_view(), name="goods"),
]

Django Rest FrameWork APIView&ModelSerializer 视图(推荐)

"""【views.py】"""
from django.http import Http404
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status

from .models import Goods
from .serializers import GoodsSerializer

class GoodsListView(APIView):
    def get(self, request, format=None):
        goods = Goods.objects.all()[:10]
        serializer = GoodsSerializer(goods, many=True)  # many=True 表示是一个 list 对象
        return Response(serializer.data)

    def post(self, request, format=None):
        serializer = GoodsSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        
------------------------------------------------------------------------------------------

"""【serializers.py】"""
from rest_framework import serializers

from .models import Goods

class GoodsSerializer(serializers.ModelSerializer):
    class Meta:
        model = Goods
        fields = ('id', 'title', 'code', 'linenos', 'language', 'style')
        # fields = "__all__"  # 调用所有字段
        
------------------------------------------------------------------------------------------

"""【urls.py】"""
urlpatterns = [
    path('goods/', GoodsListView.as_view(), name="goods"),
]

Django Rest FrameWork GenericAPIView(推荐)

GenericAPIView: 是对 APIView 的一层封装

需要重写 get、post 方法,可从 GenericAPIView 中复制出来修改
如果不写 get、post 会默认认为不接受 get、post

字段名 说明
queryset 指定作用的 model 数据范围
serializer_class 设置 View 的 serializer
lookup_field *
lookup_url_kwarg *
filter_backends *
pagination_class *
可重用的方法 说明
mixins.ListModelMixin get 请求自带 list 方法
mixins.CreateModelMixin *
mixins.RetrieveModelMixin *
mixins.DestroyModelMixin *
mixins.UpdateModelMixin *
子类视图 等价于 说明
ListAPIView ListModelMixin + GenericAPIView 提供列出模型所有信息的接口
CreateAPIView CreateModelMixin + GenericAPIView 提供创建一个模型信息的接口
RetrieveAPIView RetrieveModelMixin + GenericAPIView 提供获取一个模型信息的接口
DestroyAPIView DestroyModelMixin + GenericAPIView 提供删除一个模型信息的接口
UpdateAPIView UpdateModelMixin + GenericAPIView 提供一个视图提供列出模型所有和创建一个模型信息的接口
ListCreateAPIView ListModelMixin + CreateModelMixin + GenericAPIView 只提供更新一个模型信息的接口
RetrieveUpdateAPIView RetrieveModelMixin + UpdateModelMixin + GenericAPIView 获取一个模型信息 更新一个模型信息
RetrieveUpdateDestoryAPIView RetrieveModelMixin + UpdateModelMixin + DestroyModelMixin + GenericAPIView 获取一个模型信息 更新模型信息 删除一个模型
"""【views.py】"""
from django.http import Http404
from rest_framework.response import Response
from rest_framework import status
from rest_framework import mixins
from rest_framework import generics
from rest_framework.pagination import PageNumberPagination
from rest_framework.authentication import TokenAuthentication

from .models import Goods
from .serializers import GoodsSerializer

class GoodsPagination(PageNumberPagination):
    """
    商品自定义的分页
    """
    page_size = 20  # 设置单页的量 前端可以通过提交 page_size 参数来修改,这里只是个默认值
    max_page_size = 100  # 设置单页最大值
    page_size_query_param = 'page_size'  # 自定义每页数量请求参数
    page_query_param = "p"  # 自定义页数请求参数

class GoodsListView(mixins.ListModelMixin, generics.GenericAPIView):

    queryset = Goods.objects.all()
    serializer_class = GoodsSerializer
    pagination_class = GoodsPagination  # 调用自定义的分页
    authentication_classes = (TokenAuthentication, )  # 配置是否需要 token
    
    def get(self, request, format=None):
        goods = Goods.objects.all()[:10]
        serializer = GoodsSerializer(goods, many=True)  # many=True 表示是一个 list 对象
        return Response(serializer.data)
        
------------------------------------------------------------------------------------------

"""【serializers.py】"""
from rest_framework import serializers

from .models import Goods

class GoodsSerializer(serializers.ModelSerializer):
    class Meta:
        model = Goods
        fields = ('id', 'title', 'code', 'linenos', 'language', 'style')
        # fields = "__all__"  # 调用所有字段
        
------------------------------------------------------------------------------------------

"""【urls.py】"""
urlpatterns = [
    path('goods/', GoodsListView.as_view(), name="goods"),
]

Django Rest FrameWork GenericAPIView(推荐)

"""【views.py】"""
from rest_framework import mixins
from rest_framework import viewsets
from rest_framework.pagination import PageNumberPagination
from rest_framework.authentication import TokenAuthentication

from .models import Goods
from .serializers import GoodsSerializer

class GoodsPagination(PageNumberPagination):
    """
    商品自定义的分页
    """
    page_size = 20  # 设置单页的量 前端可以通过提交 page_size 参数来修改,这里只是个默认值
    max_page_size = 100  # 设置单页最大值
    page_size_query_param = 'page_size'  # 自定义每页数量请求参数
    page_query_param = "p"  # 自定义页数请求参数

class GoodsListView(mixins.ListModelMixin, viewsets.GenericViewSet):

    queryset = Goods.objects.all()
    serializer_class = GoodsSerializer
    pagination_class = GoodsPagination  # 调用自定义的分页
        
------------------------------------------------------------------------------------------

"""【serializers.py】"""
from rest_framework import serializers

from .models import Goods

class GoodsSerializer(serializers.ModelSerializer):
    class Meta:
        model = Goods
        fields = ('id', 'title', 'code', 'linenos', 'language', 'style')
        # fields = "__all__"  # 调用所有字段
        
------------------------------------------------------------------------------------------

"""【urls.py】"""
# 不使用 router 的配置
from goods.views import GoodsListViewSet

goods_list = GoodsListViewSet.as_view({
    'get': 'list',  # 将 get 请求绑定到 list() 上
    'post': 'create',  # 将 post 请求绑定到 create() 上
})

urlpatterns = [
    path('goods/', GoodsListView.as_view(), name="goods"),
]

Django REST FrameWork跨域

github.com/ottoyiu/dja…


DRF 的 Request 和 Response

拆分笔记:juejin.cn/post/684490…


View APIView Viewset

拆分笔记:juejin.cn/post/684490…


过滤

拆分笔记:juejin.cn/post/684490…


用户登录注册及JWT

拆分笔记:juejin.cn/post/684490…


自动生成API文档相关

www.django-rest-framework.org/topics/docu…