本代码完成的功能是:

1.根据token判断用户登录状态,然后提示用户是否登陆,

2.用户登录后,根据用户类型判断用户是否有权限查看资料

使用rest_framework一定要在配置文件设置先设置 'rest_framework',

INSTALLED_APPS = (
    ...
    'rest_framework',
)

 

Step1:数据库模型类models.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-

# Django Library
from django.db import models


class User(models.Model):
    """
    存储用户信息
    """
    user_name = models.CharField(max_length=32)
    password = models.EmailField(max_length=32)
    user_type_entry = (
        (1, 'Delux'),
        (2, 'SVIP'),
        (3, "VVIP")
    )
    user_type = models.IntegerField(choices=user_type_entry)

    def __str__(self):
        return self.user_name


class UserToken(models.Model):
    """
    存储用户登录的token值
    """
    user = models.OneToOneField("User", on_delete=models.CASCADE)
    token = models.CharField(max_length=128)


class Book(models.Model):
    """
    图书信息表
    """
    nid = models.AutoField(primary_key=True)
    title = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    # 外键字段
    publish = models.ForeignKey(to="Publish", related_name="book", related_query_name="book_query",
                                on_delete=models.CASCADE)
    # 多对多字段
    authors = models.ManyToManyField(to="Author")

    def __str__(self):
        return self.title


class Author(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    age = models.IntegerField()

    def __str__(self):
        return self.name


class Publish(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    city = models.CharField(max_length=32)
    email = models.EmailField()

    def __str__(self):
        return self.name

 

 

Step2:视图类views.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-

# Django
from django.http import JsonResponse
# Third-party Library
from rest_framework.views import APIView
from rest_framework.viewsets import ModelViewSet
# Custom Library
from app01.service import get_token
from app01.service.authentication_class import UserAuth1
from app01.service.permission_class import UserPerm
from app01.service.serializer_class import BookSerializer
from .models import User, UserToken, Book


# 图书视图类
class BookView(ModelViewSet):
    # 用户认证
    authentication_classes = [UserAuth1]
    # 权限认证
    permission_classes = [UserPerm]
    # 获取图书列表
    queryset = Book.objects.all()
    # 序列化类
    serializer_class = BookSerializer


# 用户视图类
class UserView(APIView):
    def post(self, request):
        response = dict()
        try:
            user_name = request.data['username']
            password = request.data['password']
            user_obj = User.objects.filter(user_name=user_name, password=password).first()
            if user_obj:
                access_token = get_token.generate_token()
                UserToken.objects.update_or_create(user=user_obj, defaults={"token": access_token})
                response["status_code"] = 200
                response["status_message"] = "登录成功"
                response["access_token"] = access_token
                response["user_role"] = user_obj.get_user_type_display()
            else:
                response["status_code"] = 201
                response["status_message"] = "登录失败,用户名或密码错误"
        except Exception as e:
            response["status_code"] = 202
            response["status_message"] = str(e)

        return JsonResponse(response)


# Token值视图类
class UserTokenView(APIView):
    def get(self):
        tokens = UserToken.objects.all()

 

Step3:认证组件authentication_class.py

from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import APIException
from app01.models import UserToken


# 方法1:定义认证类  
class UserAuth1(BaseAuthentication):
  def authenticate_header(self, request):
    pass
# 所有的认证逻辑都在authenticate def authenticate(self, request): user_token = request.query_params.get("token") try: token = UserToken.objects.get(token=user_token) # 后面权限会用到 return token.user, token.token except Exception: raise APIException("认证失败,用户名与密码不符!") # 方法2:定义认证类 class UserAuth2(BaseAuthentication): # 所有的认证逻辑都在authenticate def authenticate(self, request): user_token = request.query_params.get("token") try: token = UserToken.objects.get(token=user_token) # 后面权限会用到 return token.user, token.token except Exception: raise APIException("认证失败,用户名与密码不符!")

 

Step4-1:权限组件permission_class.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-
class UserPerm():
    # 自定义错误信息
    message = "您没有查看该数据的权限!"

    def has_permission(self, request, view):
        # 判断逻辑都在这里
        # 本次是根据用户user_type==3判断有
        if request.user.user_type == 2:
            return True
        return False

 

Step4-2:获取token值get_token.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# 生成一个随机字符串
import uuid


def generate_token():
    random_str = str(uuid.uuid4()).replace('-', '')
    return random_str

 

Step5:序列化组件serializer_class.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-

# Third-party Library
from rest_framework import serializers
# Custome Library
from app01.models import Book


class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        # 这里展示的字段必须是数据库中有的,或者是额外字段,或者多对多字段
        fields = ('title',
                  'price',
                  'publish',
                  'author_list',
                  'publish_name',
                  'publish_city'
                  )
        extra_kwargs = {
            'publish': {'write_only': True},
            # 这里的authors是models模型中的字段,因为是多对多,我们不想直接让其显示,所以这里限制只写
            'authors':{'write_only': True},
        }
    # 额外拓展字段,出版社名字
    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与fields字段author_list一致
    author_list = serializers.SerializerMethodField()
    # get_后面与上面的author_list要保持一致才可以
    def get_author_list(self, book_obj):
        # 拿到queryset开始循环 [{}, {}, {}, {}]
        authors = list()
        # 循环每个作者对象,获取作者名字,添加到列表authors
        for author in book_obj.authors.all():
            authors.append(author.name)
        # 返回作者列表
        return authors

 

Step6:路由urls.py

from django.contrib import admin
from django.urls import path, re_path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    re_path('user/', views.UserView.as_view()),
    re_path('books/', views.BookView.as_view({'get': 'list'}))
]