路由
只要继承了ViewSetMixin及其子类的视图类就能自动生成路由
自动生成路由
from rest_framework.routers import SimpleRouter, DefaultRouter
SimpleRouter和DefaultRouter的区别
DefaultRouter和SimpleRouter多一个根路径,显示所有注册过的路由
自动生成路由的写法
1.导入模块:from rest_framework.routers import SimpleRouter, DefaultRouter
2.实例化:router = SimpleRouter() # router=DefaultRouter()
3.注册:router.register('user',views.UserView,'user')
4.加入到urlpatterns中(两种方式)
4.1.urlpatterns += router.urls
4.2.在urlpatterns添加 path('', include(router.urls)),
"""
注意
自动生成的路由映射关系其实定死了
/books/ {'get':'list'}
/books/ {'post':'create'}
/books/1/ {'get':'retrieve'}
/books/1/ {'put':'update'}
/books/1/ {'delete':'destroy'}
所以,以后写的视图类不需要写action装饰器的话,视图类中必须要有(当然我们也可以通过action装饰器映射路由)
list、destory、retrieve、create、update方法之一
其实是必须是5个扩展类之一+GenericAPIView,或9个视图子类(ModelViewSet)
"""
action装饰器的使用
from rest_framework.decorators import action
在视图函数中 会有一些其它名字的方法 必须要使用action装饰器做映射
在视图集中,如果想要让Router自动帮助我们为自定义的动作生成路由信息,需要使用rest_framework.decorators.action装饰器
以action装饰器装饰的方法名会作为action动作名,与list、retrieve等同。
- 装饰器的参数
methods: 支持的请求方式,列表或元组类型
detail: 默认是False 控制生成的路由是不是带pk
False: /user/login/
True:/user/pk/login/
url_path: 控制生成的/user/后的路径是什么,如果不写,默认以方法名命名
/user/login/,一般跟函数名同名即可
url_name: 别名,用于反向解析
- 案例
# views.py
class UserDetail(ViewSet):
authentication_classes = []
@action(methods=['GET',],detail=False)
def show(self,request):
return Response('show user_info')
# urls.py
from app01 import views
from rest_framework.routers import SimpleRouter,DefaultRouter
router=DefaultRouter()
router.register('user_detail',views.UserDetail,'user_detail')
urlpatterns = [
path('admin/', admin.site.urls),
]
urlpatterns+=router.urls
PS: 这样写了以后可以 自动生成路由
登录接口编写
- module.py
用户表
class User(models.Model):
username = models.CharField(max_length=32)
password = models.CharField(max_length=32)
def __str__(self):
return self.username
# 用户登录记录表
# 如何区分用户是否登录了?
class UserToken(models.Model):
user = models.OneToOneField(to='User', on_delete=models.CASCADE)
token = models.CharField(max_length=32, null=True) # 用户如果没有登录,就是空,如果登录了,就有值,登录多次以最后一次为准
- views.py
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是不一样的,谁登录的,就把token存到UserToken表中
token = str(uuid.uuid4()) # 生成一个永不重复的随机字符串
# 存UserToken:如果没有记录,就是新增,如果有记录更新一下即可
# 通过user去UserToken表中查数据,如果能查到,使用defaults的数据更新,如果查不到,直接通过user和defaults的数据新增
UserToken.objects.update_or_create(defaults={'token': token}, user=user)
return Response({'code': 100, 'msg': '登录成功', 'token': token})
else:
return Response({'code': 101, 'msg': '用户名或密码错误'})
- urls.py
from rest_framework.routers import SimpleRouter, DefaultRouter
from django.conf.urls import include
router = SimpleRouter()
router.register('user',views.UserView,'user')
urlpatterns = [
path('admin/', admin.site.urls),
path('', include(router.urls)),
]
认证
- 认证类
访问接口的时候,必须登录后才能访问。我们可以通过认证类完成这一需求
需要导入from rest_framework.authentication import BaseAuthentication
from .models import UserToken
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 = UserToken.objects.filter(token=token).first()
if user_token:
return user_token.user, token # 返回两个值,一个是当前登录用户,一个是token
else:
raise AuthenticationFailed('您没有登录')
- 使用步骤
1.写一个认证类,继承BaseAuthentication
2.重写authenticate方法,在内部做认证
3.如果认证通过,返回2个值
4.认证不通过抛AuthenticationFailed异常
5.只要返回了两个值,在后续的request.user 就是当前登录用户
6.如果想让某个视图类登录后才能访问
方式一: 局部配置
class BookView(ModelViewSet):
authentication_classes = [LoginAuth,]
方式二: 全局配置
REST_FRAMEWORK={
'DEFAULT_AUTHENTICATION_CLASSES':['app01.auth.LoginAuth',]
}
局部禁用:
class BookView(ModelViewSet):
authentication_classes = []
on_delete
1、models.CASCADE
级联操作,当主表中被连接的一条数据删除时,从表中所有与之关联的数据同时被删除
2、models.SET_NULL
当主表中的一行数据删除时,从表中所有与之关联的数据的相关字段设置为null,此时注意定义外键时,这个字段必须可以允许为空
3、models.PROTECT
当主表中的一行数据删除时,由于从表中相关字段是受保护的外键,所以都不允许删除
4、models.SET_DEFAULT
当主表中的一行数据删除时,从表中所有相关的数据的关联字段设置为默认值,此时注意定义外键时,这个外键字段应该有一个默认值
5、models.SET()
当主表中的一条数据删除时,从表中所有的关联数据字段设置为SET()中设置的值,与models.SET_DEFAULT相似,只不过此时从表中的相关字段不需要设置default参数
6、models.DO_NOTHING
什么都不做,一切都看数据库级别的约束,注数据库级别的默认约束为RESTRICT,这个约束与django中的models.PROTECT相似
posted on
浙公网安备 33010602011771号