注册器组件
-
url注册器的使用
-
导入模块
from django.urls import re_path, include from .serializer import views from rest_framework import routers
-
生成一个注册器实例对象
router = routers.DefaultRouter()
-
将需要自动生成url的接口注册
router.register(r"books", views.BookView)
-
开始自动生成url
urlpatterns = [ re_path("^", include(router.urls)), ]
-
案列
-
model.py
from django.db import models from datetime import datetime # from django.contrib.auth.models import AbstractUser class UserInfo(models.Model): username = models.CharField(max_length=32, verbose_name="用户名") password = models.CharField(max_length=40, verbose_name="用户密码") user_type_entry = ( (1, "Delux"), (2, "SVIP"), (3, "VVIP") ) user_type = models.IntegerField(choices=user_type_entry) class Meta: db_table = "db_user_info" verbose_name = "用户信息" verbose_name_plural = verbose_name def get_user_type_display(self): return self.user_type_entry[self.user_type] class UserToken(models.Model): # OneToOneField一对一关系 # on_delete=models.CASCADE 当UserInfo数据表里面的数据被删除后UserToken里面的数据也随着被删除 user = models.OneToOneField("UserInfo", on_delete=models.CASCADE, verbose_name="一对一关系") token = models.CharField(max_length=128, verbose_name="token") class Meta: db_table = "db_user_token" verbose_name = "用户token" verbose_name_plural = verbose_name class AuthorInfo(models.Model): name = models.CharField(max_length=32, verbose_name="作者名称") age = models.IntegerField(verbose_name="作者年龄") class Meta: db_table = "db_author_info" verbose_name = "作者信息" verbose_name_plural = verbose_name def __str__(self): return self.name class PublishInfo(models.Model): name = models.CharField(max_length=32, verbose_name="出版社名称") city = models.CharField(max_length=32, verbose_name="出版社所在城市") email = models.EmailField(verbose_name="出版社邮箱") class Meta: db_table = "db_publish_info" verbose_name = "出版社信息" verbose_name_plural = verbose_name def __str__(self): return self.name class BookInfo(models.Model): title = models.CharField(max_length=32, verbose_name="书名") publishDate = models.DateField(default=datetime.now, verbose_name="出版日期") # max_digits小数位加整数位多少长度 decimal_places小数位长度为2 price = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="图书价格") publish = models.ForeignKey(PublishInfo, related_name="book", related_query_name="book_query", on_delete=models.CASCADE, verbose_name="出版社") # ManyToManyField多对多 authors = models.ManyToManyField(AuthorInfo, verbose_name="图书作者") class Meta: db_table = "db_book_info" verbose_name = "图书信息" verbose_name_plural = verbose_name def __str__(self): return self.title
-
url.py
from django.urls import re_path, include from .views import UserView, BookView # 导入模块 from rest_framework import routers # 生成一个注册器实例对象 router = routers.DefaultRouter() # 将需要自动生成url的接口注册 router.register(r"books", BookView) urlpatterns = [ # re_path(r"^books/$", BookView.as_view()), # re_path(r"^books/(?P<pk>\d+)/$", BookFilterView.as_view()) # re_path(r"^books/$", BookView.as_view({ # "get": "list", # "post": "create" # })), # # re_path(r"^books/(?P<pk>\d+)/$", BookView.as_view({ # "get": "retrieve", # "put": "update", # "delete": "destroy" # })), # # re_path(r"^user/$", UserView.as_view()) # 自动生成url re_path("^", include(router.urls)) ]
-
定义频率类
from rest_framework.throttling import SimpleRateThrottle class RateThrottle(SimpleRateThrottle): # 指定访问频率 # 指定每分钟5次 想指定每小时5次 5/h rate = "5/m" # 指定通过什么方式来区分用户 def get_cache_key(self, request, view): # 根据用户的ip地址 return self.get_ident(request)
-
views.py
from django.shortcuts import render from django.http import JsonResponse from rest_framework.views import APIView from rest_framework.viewsets import ModelViewSet from rest_framework.exceptions import APIException from rest_framework.authentication import BaseAuthentication from .models import BookInfo, PublishInfo, AuthorInfo, UserInfo, UserToken from .app_serializers import BookSerializer from .utils import get_token, app_throttles # 定义认证类 class UserAuth(BaseAuthentication): # 所有的逻辑都在authenticate上写 def authenticate(self, request): # 获取token值 user_token = request.GET.get("token", "") if user_token: try: # 查询token值看有没有认证过的token token = UserToken.objects.get(token=user_token) # 后面权限会用到 # token.user.username赋值给了request.user, 可以去看源码 return token.user, token.token except UserToken.DoesNotExist: raise APIException("没有认证") else: raise APIException("没有认证") class UserPerm(object): # 必须是message, 因为源码用的是message, 我们这里用message就是覆盖掉源码 # 所以返回为假时, 我们可以用message自定义你想返回给用户看到的信息 message = "您没有查看该数据的权限!" # 这是对所有数据 # 这个has_permission也是重写的 # 用户有权限必须返回真, 用户没权限必须返回假 不懂看, 源码 def has_permission(self, request, view): if request.user.user_type == 1: # request.user 获取到 认证组件返回的用户对象 # type是用户表中的一个字段 # 这里如果等于3就代表该用户有看这个数据的权限, 返回能代表真的信息就行 return True # 这里返回的东西必须需是能代表假, 因为用户没有这个权限, 所以不能等它看到数据 return False # 这是对单条数据 def has_object_permission(self, request, view, obj): if request.user.user_type == 1: # request.user 获取到 认证组件返回的用户对象 # type是用户表中的一个字段 # 这里如果等于3就代表该用户有看这个数据的权限, 返回能代表真的信息就行 return True # 这里返回的东西必须需是能代表假, 因为用户没有这个权限, 所以不能等它看到数据 return False class BookView(ModelViewSet): # 指定认证类 UserAuth authentication_classes = [UserAuth] # 指定权限类 permission_classes = [UserPerm] # 指定评率类 throttle_classes = [app_throttles.RateThrottle] queryset = BookInfo.objects.all() serializer_class = BookSerializer class UserView(APIView): def post(self, request): response = dict() # 定义需要的用户信息 fields = {"username", "password"} # 定义一个用户信息字典 user_info = dict() # fields.issubset表示 fields是request.data.keys()的子集就显示True, 相反False if fields.issubset(set(request.data.keys())): # username = request.data.get("username", "") # password = request.data.get("password", "") for key in fields: user_info[key] = request.data[key] if user_info: # **user_info字典拆包 拆包成键值对, 而不是整个字典了 列 {"a":"bb"} 拆包成 a="bb" user_instance = UserInfo.objects.filter(**user_info).first() if user_instance is not None: access_token = get_token.generate_token() # 根据user=user_instance找到了直接更新, 把default的值复制给它 # 没有找到直接创建 # 意思就是有这个token更新token, 没有这个token创建一个token UserToken.objects.update_or_create(user=user_instance, defaults={ "token": access_token }) response["status_code"] = 200 response["status_message"] = "登入成功" response["access_token"] = access_token response["user_role"] = user_instance.get_user_type_display() else: response["status_code"] = 201 response["status_message"] = "登入失败, 用户名或密码错误" return JsonResponse(response) else: return JsonResponse({"error": "参数不完整"})
-
访问一个错误路径我们可以看到, 它为我们定义了6条url
-
只要根据它定义的一个个访问就好了, 列访问books
-
还可以指定格式books.json
-
发送post就是新增一条数据
-
获取单条数据