JAVA网络爬虫
HttpClient

导航

 

权限组件

  1. 使用方式介绍

    • 定义一个权限类

      class UserPerm():
        	def has_permission(self, request, view):
            	pass
      
    • 指定权限验证的类

      class BookView(APIView):
        	# 指定认证类
          authentication_classes = [UserAuth]
        	# 指定权限验证的类
        	permission_classes = [UserPerm]
          
          queryset = BookInfo.objects.all()
          serializer = BookSerializer
      

案列

  • 导入模块

     from django.http import JsonResponse
     
     from rest_framework.views import APIView
     from rest_framework.viewsets import ModelViewSet
     from rest_framework.exceptions import APIException
    
  • url.py

    from django.urls import re_path
    from .views import UserView, BookView
    
    urlpatterns = [
        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())
    ]
    
    
  • 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
    
    
  • 序列化类

    from.models import BookInfo
    
    # 第一步: 导入模块
    from rest_framework import serializers
    
    from datetime import datetime
    
    
    class BookSerializer(serializers.ModelSerializer):
        class Meta:
            # 指定    要操作的模型类
            model = BookInfo
    
            # 指定序列化的字段
            fields = (
                "title",
                "price",
                "publishDate",
                "publish",
                "authors",
                "author_list",
                "publish_name",
                "publish_city"
            )
    
            # 指定那些字段是只写的
            # write_only只写的 (只写的 前端发送数据时要写它, 后端返回数据时没有它)
            extra_kwargs = {
                "publish": {"write_only": True},
                "authors": {"write_only": True}
            }
    
        # 自定义的字段
        # read_only只读的 (只读的 前端发送数据时不用写它, 后端返回数据时有它)
        publish_name = serializers.CharField(max_length=32, read_only=True, source="publish.name")
        publish_city = serializers.CharField(max_length=32, read_only=True, source="publish.city")
    
        author_list = serializers.SerializerMethodField()
    
        def get_author_list(self, book_obj):
            # 拿到queryset开始循环 [ {}, {}, {}]
            authors = []
    
            for author in book_obj.authors.all():
                authors.append(author.name)
            return authors
    
  • token值

    import uuid
    
    def generate_token():
      	# 把uuid残生出来的值转换成字符串, 然后以-切割在以空链接
        random_str = str(uuid.uuid4()).replace("-", "")
        return random_str
    
  • views.py

    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
    
    # 第一步: 定义认证类
    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.username, 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]
    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": "参数不完整"})
    
  1. 权限类源码
    在这里插入图片描述
posted on 2019-07-29 11:58  gmlgxx  阅读(35)  评论(0)    收藏  举报