学习笔记

drf - 学习笔记

by 猪皮怪, 2022-08-04


常规开发:前后端不分离(后端直接用render、HttpResponse给前端)

  1. Django里的FBV、CBV:

    def users(request):
     list = ['a','b','c']
     return HttpResponse(json.dumps(list))
    ->urls.py
    urlpatterns = [url(r'^students/'),views.StudentsView.as_view(),]
    
    ->views.py
    from django.views import View
    class StudentsView(View):
     def get(self,request,*args,**kwargs):
         return HttpResponst('GET')
     def post(self,request,*args,**kwargs):
         return HttpResponst('POST')
     def put(self,request,*args,**kwargs):
         return HttpResponst('PUT')
     def delete(self,request,*args,**kwargs):
         return HttpResponst('DELETE')
     def get(self,request,*args,**kwargs):
         return HttpResponst('GET')
     def get(self,request,*args,**kwargs):
         return HttpResponst('GET')

    当访问/students路径,自动识别请求模式(自动分发),不同method显示不同响应。

  2. 列表生成式:

    class Foo:
     pass
    class Bar:
     pass
    v = []
    for i in [Foo,Bar]:
     object = i()
     v.append(object)
    v = [i() for i in [Foo,Bar]]

    第一种写法等同于第二种写法,第二种写法是第一种写法的简化版,此时v就是对象列表。

  3. 面向对象

……

面试题:

1.Django中间件

  • process_request
  • process_view
  • process_response
  • process_exception
  • process_render_template

    2.中间件用途

  • 权限
  • 用户登录
  • csrfToken的实现?

    FBV:

    from django.views.decorators.csrf import csrf_exempt,csrf_protect

    在process_view方法里实现,检查视图是否被@csrf_exempt装饰,如果有,则免除csrf认证,如果全站禁止csrf认证,需要做局部认证,可在函数前用@csrf_protect装饰
    在请求体或cookie中获取token做校验

    CBV:

    from django.utils.decorators import method_decorator
    from django.views.decorators.csrf import csrf_exempt,csrf_protect
    
    # 在class之前加装饰器:
    @method_decorator(csrf_exempt,name='dispatch')

restful 规范

  1. 写一个URL,在后台根据method的不同区分增删改查(获取、创建、更新、删除)

    FBV:

    如: urlpatterns = [url('order/',views.order_view)]
    后端: def order_view(request):
    if request.method == "GET\POST\PUT\DELETE":
    return HttpResponse("……")

    CBV:

    如: urlpatterns = [url('order/',views.OrderView.as_view())]
    后端: class OrderView(View):
    def get、post、put、delete(self,request,args,*kwargs):
    return HttpResponse("……")

Django restful framework

pip3 install djangorestframework

认证:

如何控制用户使用接口?

  • 随机字符串(token)
  • 有些api需要用户登录才能使用,有些不需登录即可使用。

    1. 创建两张表,一张存user登陆信息,另一张存用户token。
    2. 用户登陆,创建token并保存到数据库
    3. 认证流程原理:

写认证的时候:

  1. 创建一个类:

_from _rest_framework.authentication _import _BaseAuthentication
继承BaseAuthentication类,实现两个方法,重要的是实现authenticate方法。authenticate_header方法可以直接pass

  1. authenticate方法有三种返回值:

    1. None,表示让下一个认证来执行认证。
    2. _from _rest_framework _import _exceptions

raise exceptions.AuthenticationFailed('认证失败'),抛出异常。

  3. (元素1,元素2)。元素1赋值给request.user,元素2赋值给request.auth。
  1. 全局/局部认证。

    1. 局部:在views视图里写局部字段,只对单个class视图进行单个认证
    2. 全局:使用setting配置文件:(写的是认证类的路径!!!)

      1. REST_FRAMEWORK = {
        "DEFAULT_AUTHENTICATION_CLASSES":['api.utils.auth.FirstAuthtication','api.utils.auth.Authtication',],
        'UNAUTHENTICATED_USER':_None_,
        'UNAUTHENTICATED_TOKEN':_None_,

}

权限:

  1. from rest_framework.permissions import BasePermission,继承BasePermission类,实现has_permission(self,request,view)方法。

    1. 返回值有两种:False和True。
  2. 如果返回False,要写message=‘自定义信息’。
  3. 全局/局部在setting里设置。DEFAULT_PERMISSION_CLASSES

访问频率控制:

  1. 继承BaseThrottle,实现_allow_request_以及_wait_

  1. 继承SimpleRateThrottle,实现get_cache_key以及scope = 'test'字段(配置文件中的key)

    全局、局部使用

版本:

  1. 版本可通过URL的GET形式传参。

    #    http://127.0.0.1:8000/api/user/?v=2
    
    class ParamVersion(object):
     def determine_version(self,request,*args,**kwargs):
         v = request.query_params.get('v')
         return v
    
    class UsersView(APIView):
     versioning_class = ParamVersion
     def get(self,request,*args,**kwargs):
         print(request.version)
         return HttpResponse('user list')
  2. 通过URL中的正则表达式传递。

    # 应用的urls.py中:
    urlpatterns = [
     re_path(r'^(?P<version>[v1|v2]+)/user/$',views.UsersView.as_view())
    ]
    
    
    # settings.py中
    REST_FRAMEWORK = {"DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning",}

解析器:

全局配置

# settings.py中
REST_FRAMEWORK = {
    "DEFAULT_PARSER_CLASSES":['rest_framework.parsers.JSONParser'],
}

# 视图中可通过request.data获取数据

局部配置

可在视图函数局部加入parser_classes = [FileUploadParser,],然后用request.FILES获取相关数据即可。

序列化

写一个类,可以继承serializers.Serializer或serializers.ModelSerializer。

class RolesSerializer(serializers.Serializer):
    id = serializers.IntegerField()
    title = serializers.CharField()
    
# 或
class UserInfoSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.UserInfo
        fields = '__all__'
        # fields = ['id','username','password']

对于自定义的字段:

  1. xxx = serializers.CharField(source='xxxx.xxxx')

  1. xxx = serializers.SerializerMethodField(),如下:

    class UserInfoSerializer(serializers.ModelSerializer):
     # 多对多的做法
     rls = serializers.SerializerMethodField()
     def get_rls(self, row):
         row_obj_list = row.roles.all()
         ret = []
         for i in row_obj_list:
             ret.append({"id": i.id, "title": i.title})
         return ret
    
     class Meta:
         model = models.UserInfo
         fields = ['id','username','password','xxx','rls',]

    深度控制

    class UserInfoSerializer(serializers.ModelSerializer):
     class Meta:
         model = models.UserInfo
         fields = ['id','username','password','group','roles']
         depth = 1   #默认0层,深度控制建议1~10之间

    生成链接

    # urls.py中
    urlpatterns = [re_path(r'^(?P<version>[v1|v2]+)/group/(?P<pk>\d+)$',views.GroupView.as_view(),name='gp'),]
    
    # views.py中
    class UserInfoSerializer(serializers.ModelSerializer):
     group = serializers.HyperlinkedIdentityField('gp',lookup_field='group_id',lookup_url_kwarg='pk')
     class Meta:
         model = models.UserInfo
         fields = ['id','username','password','group','roles']
         depth = 0   #默认0层,深度控制建议1~10之间
    
    class UserInfoView(APIView):
     def get(self,request, *args, **kwargs):
         users = models.UserInfo.objects.all()
         ser = UserInfoSerializer(instance=users,many=True,context={'request': request})
         ret = json.dumps(ser.data, ensure_ascii=False)
         return HttpResponse(ret)

    请求数据校验(接收数据的校验)

    class UserGroupSerializer(serializers.Serializer):
     title = serializers.CharField(error_messages={'required':'title不能空'})
    
    class UserGroupView(APIView):
     def post(self, request, *args, **kwargs):
         ser = UserGroupSerializer(data=request.data)
         if ser.is_valid():
             print(ser.validated_data['title'])
         else:
             print(ser.errors)
         return HttpResponse('提交de数据')

    自定义验证规则

分页

普通分页

# views.py中
from api.utils.serializers.pager import PagerSerializers
from rest_framework.response import Response
from rest_framework.pagination import PageNumberPagination
# 自定义分页
class MyPageNumberPagination(PageNumberPagination):
    page_size = 2
    # 控制一页显示个数的URL字段
    page_size_query_param = 'size'
    # 控制size最大能拿多少个数据
    max_page_size = 4

class Pager1View(APIView):
    def get(self, request, *args, **kwargs):
        # 获取所有数据
        roles = models.Role.objects.all()
        # ret = json.dumps(ser.data)

        # 创建分页对象
        # pg = PageNumberPagination()

        # 使用自定义创建的更多功能的分页对象
        pg = MyPageNumberPagination()
        # 数据库中获取分页数据
        pager_roles = pg.paginate_queryset(roles,request,self)
        # 对数据序列化
        ser = PagerSerializers(instance=pager_roles,many=True)
        
        # 传分页后的正常数据信息
        # return Response(ser.data)
        # 传分页后的更多信息
        return pg.get_paginated_response(ser.data)

    
# settings.py中
REST_FRAMEWORK = {"PAGE_SIZE":2}

从第n个数据向后取

from api.utils.serializers.pager import PagerSerializers
from rest_framework.pagination import LimitOffsetPagination

class MyPageNumberPagination(LimitOffsetPagination):
    default_limit = 2
    limit_query_param = 'limit'
    offset_query_param = 'offset'
    max_limit = 3

class Pager1View(APIView):
    def get(self, request, *args, **kwargs):
        # 获取所有数据
        roles = models.Role.objects.all()

        # 使用自定义创建的更多功能的分页对象
        pg = LimitOffsetPagination()
        # 数据库中获取分页数据
        pager_roles = pg.paginate_queryset(roles,request,self)
        # 对数据序列化
        ser = PagerSerializers(instance=pager_roles,many=True)

        # 传更多信息
        return pg.get_paginated_response(ser.data)


# url中:http://127.0.0.1:8000/api/v1/pager1/?limit=2&offset=4

加密分页

from api.utils.serializers.pager import PagerSerializers
from rest_framework.pagination import CursorPagination

class MyPageNumberPagination(CursorPagination):
    cursor_query_param = 'cursor'
    page_size = 3
    ordering = 'id'
    page_size_query_param = 2
    max_page_size = 5

class Pager1View(APIView):
    def get(self, request, *args, **kwargs):
        # 获取所有数据
        roles = models.Role.objects.all()

        # 创建分页对象
        # pg = PageNumberPagination()

        # 使用自定义创建的更多功能的分页对象
        pg = MyPageNumberPagination()
        # 数据库中获取分页数据
        pager_roles = pg.paginate_queryset(roles,request,self)
        # 对数据序列化
        ser = PagerSerializers(instance=pager_roles,many=True)

        # 传更多信息
        return pg.get_paginated_response(ser.data)

高级视图操作(直接实现四操作)

# views.py中
# 直接实现增删改查
from api.utils.serializers.pager import PagerSerializers
from rest_framework.viewsets import ModelViewSet
class View2View(ModelViewSet):
    queryset = models.Role.objects.all()
    serializer_class = PagerSerializers
    pagination_class = MyPageNumberPagination
    
    
# urls.py中,一个URL要写两个路由
urlpatterns = [re_path(r'^(?P<version>[v1|v2]+)/view2/$',views.View2View.as_view({'get':'list','post':'create'})),
    re_path(r'^(?P<version>[v1|v2]+)/view2/(?P<pk>\d+)/$',views.View2View.as_view({'get':'retrieve','delete':'destroy','put':'update','patch':'partial_update'})),]

自动生成路由(直接覆盖四操作的路由系统)

from django.urls import path, include, re_path
from api import views
from rest_framework import routers
router = routers.DefaultRouter()
router.register(r'view2',views.View2View)

urlpatterns = [re_path(r'^(?P<version>[v1|v2]+)/',include(router.urls))]

渲染器

# settings.py中
REST_FRAMEWORK = {"DEFAULT_RENDERER_CLASSES":['rest_framework.renderers.JSONRenderer']}
none
猪皮怪

作者: 猪皮怪

2025 © typecho & esia.asia