Django里rest_framework的注册器组件

注册器组件

  1. 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就是新增一条数据

  • 获取单条数据
    在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

只因为你温柔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值