路由生成步骤
第一步:导入
from rest_framework.routers import SimpleRouter, DefaultRouter
SimpleRouter与DefaultRouter区别:
DefaultRouter比SimpleRouter多一个跟路径显示所有注册过的路由
第二步:实例化
router = SimpleRouter()
第三步:注册路由
router.register('user',views.UserView,'user')
register参数:
prefix:访问视图函数的路由前缀
viewset:视图类
base_name:路由别名的前缀
第四步:添加路由到urlpatterns中
方式一:
urlpatterns += router.url
方式二:
from django.urls import path,include urlpatterns = [ path('',include(router.urls)), ]
ps:自动生成的路由映射关系其实定死了对应五个视图扩展类的五个方法,所以视图类中必须要有list、destroy、retrieve、create、update方法之一,其实是必须是五个视图扩展类之一+GenericAPIView或九个视图子类
action装饰器
在视图函数中有时候会自定义一些其他名字的方法,自定义方法自动生成路由需要借助action装饰器来做映射
action(methods=None, detail=None, url_path=None, url_name=None, **kwargs)
action参数
methods:支持的请求方式,列表
detail:控制生成的路由是否带pk,默认是False
url_path:控制url路径后面的路径是什么 不写为函数名
url_name:别名,用于反向解析
具体使用
class UserView(ViewSet): @action(methods=['POST',],detail=False,url_path='login') def login(login(self,request): pass
认证类
一.登陆接口编写
models.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): @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 router = SimpleRouter() router.register('user',views.UserView,'user') urlpatterns = [ path('admin/', admin.site.urls), path('', include(router.urls)), ]
二.接口必须认证登陆后才可以访问
1.写一个认证类,继承BaseAuthentication
2.重写authenticate方法在内部进行认证
3.认证通过返回两个值
4.认证不通过抛AuthenticationFailed异常
5.只要返回了两个值后续的request.user就是当前登陆用户
# 新建一个auth.py文件 from rest_framework.authentication import BaseAuthentication from rest_framework.exceptions import AuthenticationFailed from .models import UserToken class LoginAuth(BaseAuthentication): # 重写验证方法 def authenticate(self, request): token = request.GET.get('token') token_view = UserToken.objects.filter(token=token).first() if token_view: return token_view.user,token else: raise AuthenticationFailed('您还没有登陆')
三.视图类认证方式
全局配置
'''在settings.py配置文件中添加全局配置''' REST_FRAMEWORK={ 'DEFAULT_AUTHENTICATION_CLASSES':['app01.auth.LoginAuth',] }
局部配置
'''在视图类中添加authentication_classes''' class BookView(ModelViewSet): authentication_classes = [LoginAuth,] serializer_class = BookModelSerializer queryset = Book.objects.all()
ps:如果使用了全局配置但是又有视图类不想让它认证就可以进行局部禁用,在视图类中添加authentication_classes=[]