首页 > 其他分享 >drf自动生成路由、on_delete、登录认证

drf自动生成路由、on_delete、登录认证

时间:2022-10-08 21:48:33浏览次数:51  
标签:序列化 models 视图 token drf 路由 delete

目录

回顾

一、drf入门

1.前后端开发模式

​ 前后端分离:drf方便我们大人们方便我们快速写出接口
​ 前后端混合:bbs 模板语法

2. API接口:前后端交互的媒介

3.接口测试工具:postman

4.restful规范十条

5.drf快速入门

6.必须继承APIView写视图类

  • View的执行流程:cbv的执行流程
    路由中:视图类.as_view() --> 本质是:View的as_view内部的view闭包函数中的dispatch,根据请求方式执行视图函数中的方法
  • APIView的执行流程
    路由中:视图类.as_view() --> 本质是:APIView的as_view去掉csrf,调用父类的as_view
    请求来了,执行的是去掉了csrf的View的as_view内的view闭包函数
    self.dispatch --> APIView
    --包装了新的request
    --执行三大认证
    --处理全局异常
  • 新的Request
    1. 包装了老的request:request._request
    2. 为了使新的request和原来的使用方法一致:重写了__getattr__
    3. 新的方法(伪装成了属性):data
      body中提交的数据都在里面
    4. query_params:地址栏中的数据
    5. 文件、其他都没有差别

二、序列化组件

1.功能

  • 帮助我们快速实现:序列化反序列化数据校验

  • 如何定义:

    1. 写一个序列化类继承(Serializer/ModelSerizlizer)

    2. 写要序列化的字段(字段类,字段参数:read_only,write_only)

    3. 字段自己的规则:局部钩子、全局钩子

    4. 序列化修改字段格式:

      • 序列化中写SerializerMethodField,get_字段名

      • 表模型中写方法(返回字典Dict Field、列表ListField)

      • json格式字符串必须用"",如{"name":"zhang","age":16},如果是{'name':'zhang','age':16}就不是json格式,js识别不了。

      • 在字典中则""和''都可以正常字典使用。

  • 在视图类中使用

    # 继承Serializer写序列化类
        ser = BookSerializer(instance=要序列化的对象,many=True)
    
        ser = BookSerizlizer(data=request.data)
    
        ser = BookSerializer(instance=要修改的对象,request.data)
    
        ser.data 序列化后的数据,字典格式
    
        校验数据:
            错误数据:ser.errors
    
        ser.save():通过判断instance是否为空,觉得调用的是create还是update
    
        如果继承了Serializer,必须重写create和update
    
    # 继承ModelSerializer写序列化类
    	1.class Meta:
            model=表模型
            fields='__all__'[新增的字段一定要在这里注册]
            extra_kwargs={'name':{read_only:True}}  # 对字段进行添加
        2.重写某个字段
        3.序列化修改字段格式跟之前一样
        4.一般不需要重写create和update
        	一次性提交的数据涉及多个表时可能会需要重写
            (但是如果数据中能明确对应表关系的话也可以不重写,比如数据值有author_id)
        5.注意:直接从表模型中映射的字段也有字段类和字段属性
    

三、请求与响应

  1. 请求对象,响应对象(Request,Response)

  2. 原生django响应头里写内容

    响应对象[内容]

  3. drf能够解析的请求格式:局部配置和全局配置

  4. drf的响应格式:局部配置和全局配置

四、视图类

1.两个视图基类

- APIView
- GenericAPIView:继承了APIView,有几个属性和方法
  queryset = None  # 要序列化的数据
  serializer_class = None  # 序列化类
  lookup_field = 'pk'  # 针对单条数据的过滤
  get_queryset()  # 获取要序列化的数据,比self.queryset扩展性高
  get_object()  # 获取单个对象
  get_serializer()  # 获取序列化类对象

2. 5个视图扩展类

	- ListModelMixin
	- CreateModelMixin
	- RetrieveModelMixin
	- UpdateModelMixin
	- DestoryModelMixin

​ 需要配合GenericAPIView用

3. 9个视图子类

	- ListAPIView
	- CreateAPIView
	- ListCreateAPIView
	- RetrieveAPIView
	- UpdateAPIView
	- DestoryAPIView
	- RetrieveUpdateAPIView
	- RetrieveDestoryAPIView
	- RetrieveUpdateDestoryAPIView

​ 视图类,继承了GenericaAPIView+5个视图扩展类之几+get/post/delete/put

4.视图集

  • ViewSetMixin

    重写了as_view,一旦继承了它及其子类,路由写法改变,as_view中加字典做映射

    {'get':'list','put':'update'}

  • ViewSet = ViewSetMixin+APIView

    class TestView(ViewSet):
        def login(self,request):
            pass
    
  • GenericViewSet=ViewSetMixin+GenericAPIView

    class TestView(GenericViewSet):
        queryset = None
        serializer_class = None
        def login(self,request):
            pass
    
  • ModelViewSet

    路由写法改变,两个类属性:queryset,serializer_class

  • ReadOnlyModelViewSet

    路由写法改变,两个类属性:queryset,serializer_class

    只有读取所有和获取单条,没有增加、修改

今日内容

一、路由

​ 只要继承了ViewSetMixin及其子类的视图类,路由都可以换个写法

例如:path('books/', views.BookView.as_view({'get': 'list', 'post': 'create'}))

1.自动生成路由

# urls.py
from django.contrib import admin
from django.urls import path, include
from app01 import views

# drf提供两个路由类,以后继承了ViewSetMixin及其子类的视图类,路由都可以使用这两个路由来自动生成

# 自动生成路由步骤
# 第一步:导入
from rest_framework.routers import SimpleRouter, DefaultRouter

# 第二步:实例化
router = SimpleRouter()
# router = DefaultRouter()  # 区别是DefaultRouter会多一个根路径^$ [name='api-root']
# 第三步:注册路由(可以注册多个)
# 注册参数:路径、视图类、别名(可以不写)
router.register('books', views.BookView,'books')
router.register('publish', views.BookView)
router.register('user', views.BookView)
urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include(router.urls))
]
'''
第四步:把自动生成的路由添加到urlpatterns中
方式一:path('', include(router.urls))
方式二:urlpatterns += router.urls
'''
# urlpatterns += router.urls
  • SimpleRouter 和DefaultRouter的区别

    虽然看起来多了很多,实质上就是DefaultRouter会多一个根路径^$ [name='api-root']

    • router = SimpleRouter()

      image

    • router = DefaultRouter()

      image

3.action装饰器的使用

二、登录接口编写

1.models.py

from django.db import models


# Create your models here.
class User(models.Model):
    username = models.CharField(max_length=32)
    password = models.CharField(max_length=16)

    def __str__(self):
        return self.username
# 用户登录记录表
# 区分用户是否登录
class Token(models.Model):
    token = models.CharField(max_length=32, null=True)
    # 如果用户没有登录token为空,如果登录了就会有值,登录多次保留最后一次 
    
    user = models.OneToOneField(to='User', on_delete=models.DO_NOTHING)

2.views.py

from rest_framework.response import Response
from rest_framework.decorators import action

'''
注意:
    继承ViewSetMixin及其子类的视图类都可以自动生成路由
    但是映射关系是定死的(get:list,post:create,get:retrieve,put:update,delete:destroy)
    自己想做映射关系需要使用装饰器action
'''
import uuid  # 随机产生字符串


class UserView(ViewSetMixin, APIView):

    @action(methods=['POST', ], detail=False, url_path='login')
    def login(self, request):
        res = {'code': 100, 'msg': '登陆成功'}
        # 取出前端传入的用户名密码,校验通过:返回登陆成功;校验失败:返回登录失败
        username = request.POST.get('username')
        password = request.POST.get('password')
        print(username, password)
        user = User.objects.filter(username=username, password=password).first()
        if user:
            # 登陆成功,每个用户生成的token都不同,把token保存到Token表中
            token = uuid.uuid4()
			'''
				生成随机字符串(永不重复)
            	如果Token没有记录就新增,如果有就更新
            	通过user去Token表中查数据:
            		能查到:使用defaults的数据更新,
            		查不到:直接通过user和defaults的数据新增
			'''
            Token.objects.update_or_create(defaults={'token': token}, user_id=user.id)
            res['token'] = token
            return Response(res)
        else:
            res['code'] = 101
            res['msg'] = '用户名或密码错误'
            return Response(res)

3.urls.py

from django.contrib import admin
from django.urls import path, include
from app01 import views
from rest_framework.routers import SimpleRouter, DefaultRouter

router = SimpleRouter()
router.register('user', views.UserView, 'user')
urlpatterns = [
    path('admin/', admin.site.urls),

    path('', include(router.urls)),
]


三、on_delete

  • CASCADE:级联删除
  • PROTECT:保护模式,采用该选项,删除时会抛出ProtectedError错误。
  • SET_NULL:置空模式,删除的时候,外键字段被设置为空
  • SET_DEFAULT:置默认值,删除的时候,外键字段设置为默认值
  • SET:自定义一个值
on_delete=None
# 删除关联表中的数据时,当前表与其关联的field的行为

on_delete=models.CASCADE
# 删除关联数据,与之关联也删除

on_delete=models.DO_NOTHING
# 删除关联数据,什么也不做

on_delete=models.PROTECT,
# 删除关联数据,引发错误ProtectedError

models.ForeignKey('关联表', on_delete=models.SET_NULL, blank=True, null=True)

on_delete=models.SET_NULL,
# 删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空,一对一同理)

# models.ForeignKey('关联表', on_delete=models.SET_DEFAULT, default='默认值')

on_delete=models.SET_DEFAULT,
# 删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值,一对一同理)

on_delete=models.SET(值),
# 删除关联数据,与之关联的值设为指定的值

四、认证

1.需求

访问接口,必须登录后才能访问

2.通过认证完成,使用步骤

  • 写一个认证类:LoginAuth,继承BaseAuthentication

  • 重写authenticate方法,在内部做认证

  • 认证通过:返回两个值(当前用户 token)

  • 认证失败:抛AuthenticationFailed异常

  • 只要返回了两个值,后续的request.user 就是当前登录用户

  • 如果想让某个视图类登录后才能访问

    # 方式一:
    	class TestView():
        	authentication_classes = [LoginAuth, ]
    
     # 方式二:
    	全局配置
    	REST_FRAMEWORK = {
        'DEFAULT_AUTHENTICATION_CLASSES': ['app01.auth.LoginAuth', ]
    }
        局部禁用:
        	class TestView():
        		authentication_classes = []
    
    

3.认证类

from .models import Token
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed


class LoginAuth(BaseAuthentication):
    def authenticate(self, request):
        # 在这里做认证,校验用户是否登录(带了token并且能查到就是登录,返回两个数据值,否则就是没登录抛异常)
        # 用户带的token如何获取?==> 后端人员设定:放在请求地址中
        token = request.GET.get('token')
        # 通过token查询该token是否在表中有记录
        user_token = Token.objects.filter(token=token).first()
        if user_token:
            return user_token.user, token  # 返回两个值:当前用户  token
        else:
            raise AuthenticationFailed('您没有登录')

标签:序列化,models,视图,token,drf,路由,delete
From: https://www.cnblogs.com/Zhang614/p/16770292.html

相关文章

  • 自动生成路由、登录接口与登录认证
    路由自己写的路由path('books/',views.BookView.as_view({'get':'list','post':'create'})),path('admin/<int:pk>',views.BookView.as_view({'get':'retrieve',......
  • 【Django-rest-framework框架】第06回 路由、登录、认证
    目录1.自动生成路由1.1本质1.2使用步骤1.3SimpleRouter与DefaultRouter区别1.4自动生成的路由映射关系其实定死了1.5action装饰器的使用1.6action装饰器的使用1.7......
  • 【2022-10-08】 DRF从入门到入土(六)
    drf之路由组件自动生成路由#drf提供了两个路由类,只要继承了ViewSetMixin及其子类的视图类,就可以使用这两个路由类来自动生成路由#使用步骤如下:1导入模块:fromr......
  • drf-06
    路由层自动生成路由 1.路由类导入fromrest_framework.routersimportSimpleRouter,DefaultRouter 2.实例化router=SimpleRouter() 3.注册router.register......
  • 自动生成路由,action装饰器,登录接口,认证
    自动生成路由action装饰器的使用登录接口编写认证自动生成路由补充:  1.只要继承了ModelViewSet就要在路由中as_view()内添加字典的形式#path('book......
  • 浅谈-动态路由之OSPF的理解
    路由在网络中,路由相当于就是一张地图,让路由器知道这个对应的IP数据包应该往哪端口、网段走;而这个“地图”我们称之为路由表,不同的目的IP路由表的下一个跳也不同,其生成方......
  • drf学习笔记
    今日内容概要路由登录接口编写认证今日内容详细路由对于视图集ViewSet,我们除了可以自己手动指明请求方式与动作action之间的对应关系,还可以使用Routers来帮助......
  • drf-6
    前5天内容小回顾一、drf入门亲后端开发模式    分离:drf方便我们快速写出接口    混合:bbs、模板语法API接口:前后端交互的媒介接口测试工具:postman(不止这一......
  • 今日内容 路由与登录认证
    路由自动生成路由步骤:1导入:fromrest_framework.routersimportSimpleRouter,DefaultRouter2实例化:router=SimpleRouter()3注册:router.registe......
  • vue路由加载页面
    当vue路由切换时,有时候会出现短暂白屏,需要添加一个加载状态参考:buildadmin地址:https://demo.buildadmin.com/#/利用vue的路由导航守卫:beforeEach、afterEach来判断显示......