drf 自动生成路由 认证类编写
文章目录
1、自动生成路由
1.1、自动生成路由 编写
自动生成路由写法
-
导入:
from rest_framework.routers import SimpleRouter, DefaultRouter
-
实例化:
router = SimpleRouter()
-
注册:
router.register('user', views.UserView,'user')
-
加入到
urlpatterns
中(两种方式)urlpatterns += router.urls
path('',include(router.urls))
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('books/', views.BookViews.as_view()),
path('publishs/', views.PublishViews.as_view()),
path('book/<int:pk>/', views.BookView.as_view()),
path('publish/<int:pk>/', views.PublishView.as_view()),
path('',include(router.urls)) # 方法二:
]
#方法一
# urlpatterns += router.urls
自动生成路由映射关系其实定死了
as_view({'get': 'list', 'post': 'create'}))
as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'}))
以后写的视图类不需要写action装饰器的话,视图类中必须要有
list,destroy,retrieve,create,update
方法之一
其实必须是5个视图扩展类之一+GenericAPIView
9个视图子类,ModelViewSet
SimpleRouter 和 DefaultRouter
DefaultTouter比SimpleRouter
多一个跟路径,显示所有注册过的路由
1.2、action 装饰器的使用
在视图函数中,会有一些其它名字的方法,必须要使用action装饰器做映射
methods: 支持请求方式,列表
detail: 默认是False 控制生成的路由时 /user/login/
还是/user/pk/login/
是不是带pk
url_path: 控制生成的/user/后的路径是什么,如果不写,默认以方法命名 /user/login/,一般跟函数名同名即可
url_name: 别名,用于反向解析
class UserView(ViewSet):
@action(methods=['POST'],detail=False,url_path='login')
def login(self,request):
2、登录接口编写
2.1、models.py
如何区分用户是否登录?
创建一个用户登录记录表,创建一个字段,如果存有值则代表登录,如果没有登录则为空
登录多次以最后一次为准
class Token(models.Model):
token = models.CharField(max_length=64,null=True)
user = models.OneToOneField(to='User',on_delete=models.CASCADE)
2.2、views.py
当用户登录成功,不同用户生成的tokrn是不一样的
可以用 uuid.uuid4()
在Token表中 如果 没有记录就是新增,如果有记录就是更新
update_or_create
数据存在则更新,数据不存在则新增
class UserView(ViewSet):
authentication_classes = []
@action(methods=['POST'],detail=False,url_path='login')
def login(self,request):
username = request.data.get('username')
password = request.data.get('password')
user = User.objects.filter(username=username,password=password).first()
if user:
# 生成随机字符串
token=str(uuid.uuid4())
# 更新或新增数据
Token.objects.update_or_create(user=user,defaults={'token':token})
return Response({'code':100,'msg':'登录成功','token':token})
return Response({'code':101,'msg':'账号或密码错误'})
2.3、urls.py
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)),
]
3、认证
访问接口,必须登录后才能访问
通过认证类完成,使用步骤
-
写一个认证类,继承
BaseAuthentication
-
重写
authenticate
方法,在内部做认证 -
如果认证通过,返回2个值
-
认证不通过抛异常
AuthenticationFailed
-
只要返回两个值,在后续的
request.user
就是当前登录用户 -
如果想让某个视图,登录后才能访问
方式一:
class BookView(ModelviewSet): authentication_classes = [loginAuth]
方式二: 全局配置
REST_FRAMEWORK={ 'DEFAULT_AUTHENTICATION_CLASSES':['app01.auth.LoginAuth',] }
局部禁用
authentication_classes = []
3.1、认证类
from app01.models import Token
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
#需要继承 BaseAuthentication
class Login_Auth(BaseAuthentication):
# 注意 是重写 authenticate 方法 所以名字 不可乱取
def authenticate(self, request):
token = request.GET.get('token')
user_token = Token.objects.filter(token=token).first()
if user_token:
# 返回两个值,一个是当前登录用户,一个是token
return user_token.user, token
raise AuthenticationFailed('您还未登录,请先登录')
4、级联删除 字段
CASCADE: 默认的,级联删除
**SET_NULL: ** 设置ForeignKey 为 null; 这个只有设置了null 为 True的情况才能用
**SET_DEFAULT: ** 设置 ForeignKey 为默认值; 默认值必须预先设置
**SET(): ** 设置为某个方法返回的值
**PROTECT: ** 通过抛出django.db.models.ProtectedErrordjango.db.models.ProtectedError错误来阻止删除关联的对象
**DO_NOTHING: ** 什么都不做,如果数据库设置必须关联则会报IntegrityError错