一、创建LoginAuth类完成认证过程
urls.py
url(r'^login/', views.Login.as_view()), url(r'^books/', views.Books.as_view()),
models.py
from django.db import models # Create your models here. class UserInfo(models.Model): name = models.CharField(max_length=32) # 写choice user_choice=((0,'普通用户'),(1,'会员'),(2,'超级用户')) # 指定choice,可以快速的通过数字,取出文字 user_type=models.IntegerField(choices=user_choice,default=0) pwd = models.CharField(max_length=32) class UserToken(models.Model): token = models.CharField(max_length=64) user = models.OneToOneField(to=UserInfo) class Book(models.Model): nid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) price = models.DecimalField(max_digits=5, decimal_places=2) publish_date = models.DateField() publish = models.ForeignKey(to='Publish', to_field='nid', on_delete=models.CASCADE) authors = models.ManyToManyField(to='Author') def __str__(self): return self.name class Author(models.Model): nid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) age = models.IntegerField() author_detail = models.OneToOneField(to='AuthorDatail', to_field='nid', unique=True, on_delete=models.CASCADE) class AuthorDatail(models.Model): nid = models.AutoField(primary_key=True) telephone = models.BigIntegerField() birthday = models.DateField() addr = models.CharField(max_length=64) 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 def test(self): return self.email
迁移数据库
python3 manage makemigrations
python3 manage migrate
app01/MySerializer.py
from rest_framework import serializers from app01 import models class BookSerializer(serializers.ModelSerializer): class Meta: model = models.Book fields='__all__'
views.py
from django.shortcuts import render from django.http import JsonResponse from rest_framework.views import APIView from app01 import models import hashlib import time from django.core.exceptions import ObjectDoesNotExist from app01 import MySerializer # Create your views here. def get_token(name): # 生成一个md5对象 md5 = hashlib.md5() # 往里添加值,必须是bytes格式 # time.time()生成时间戳类型,转成字符串,再encode转成bytes格式 md5.update(str(time.time()).encode('utf-8')) md5.update(name.encode('utf-8')) return md5.hexdigest() class Login(APIView): authentication_classes = [] def post(self, request, *args, **kwargs): response = {'status': 100, 'msg': '登录成功'} name = request.data.get('name') pwd = request.data.get('pwd') try: user = models.UserInfo.objects.get(name=name, pwd=pwd) # 校验通过,登录成功,生成一个随机字符串(身份标识)token token = get_token(name) # 保存到数据库 # update_or_create更新或者创建 models.UserToken.objects.update_or_create(user=user, defaults={'token': token}) response['token'] = token except ObjectDoesNotExist as e: response['status'] = 101 response['msg'] = '用户名或密码错误' except Exception as e: response['status'] = 102 # response['msg']='未知错误' response['msg'] = str(e) return JsonResponse(response, safe=False) from rest_framework import exceptions class LoginAuth(): # 函数名必须叫这个名字,接收必须两个参数,第二个参数是request对像 def authenticate(self, request): # 从request对像中取出token (也可以从其他地方中取) token = request.query_params.get('token') # 去数据库中查询 ret = models.UserToken.objects.filter(token=token) if ret: # 可以查到,说明认证通过,返回空 return None # 否则会报异常 raise exceptions.APIException('认证失败') from rest_framework.request import Request # class Books(APIView): # # 列表中类型不能加括号 # authentication_classes = [LoginAuth, ] # # def get(self, request, *args, **kwargs): # response = {'status': 100, 'msg': '查询成功'} # # 必须登录以后,才能获取数据 # # 取出token,取数据库验证,是否登录 # token = request.query_params.get('token') # ret = models.UserToken.objects.filter(token=token) # if ret: # # 认证通过,是登录用户 # ret = models.Book.objects.all() # book_ser = MySerializer.BookSerializer(ret, many=True) # response['data'] = book_ser.data # else: # response['status'] = 101 # response['msg'] = '认证不通过' # return JsonResponse(response, safe=False) # 与上面的Books类功能一样,但比上面的那个更加简洁。 class Books(APIView): # 列表中类型不能加括号 authentication_classes = [LoginAuth, ] def get(self, request, *args, **kwargs): response = {'status': 100, 'msg': '查询成功'} ret = models.Book.objects.all() book_ser = MySerializer.BookSerializer(ret, many=True) response['data'] = book_ser.data return JsonResponse(response, safe=False)
数据库中添加数据测试:
使用Postman测试:
功能:登录后方可查看书的详情信息
使用数据库中的用户名与密码登录服务:
使用token登录来验证查询书的详情信息
若是token验证不成功,就会返回:
二、认证组件的全局使用与局部使用
urls.py、models.py、不变
局部使用:
views.py
from app01.MyAuth import LoginAuth class Books(APIView): # 列表中类型不能加括号 # 认证组件局部使用 authentication_classes = [LoginAuth, ] # 认证组件,局部禁用 authentication_classes = [] def get(self, request, *args, **kwargs): response = {'status': 100, 'msg': '查询成功'} ret = models.Book.objects.all() book_ser = MySerializer.BookSerializer(ret, many=True) response['data'] = book_ser.data return JsonResponse(response, safe=False)
app01/MyAuth.py
from rest_framework import exceptions from app01 import models # 用dnf 认证,写一个类 class LoginAuth(): # 函数名必须叫这个名字,接收必须两个参数,第二个参数是request对像 def authenticate(self, request): # 从request对像中取出token (也可以从其他地方中取) token = request.query_params.get('token') # 去数据库中查询 ret = models.UserToken.objects.filter(token=token) if ret: # 可以查到,说明认证通过,返回空 return None # 否则会报异常 raise exceptions.APIException('认证失败')
-全局使用
-在setting中配置:
REST_FRAMEWORK={ 'DEFAULT_AUTHENTICATION_CLASSES':['app01.MyAuth.LoginAuth',], }
-局部禁用,views.py中有:
认证组件,局部禁用 authentication_classes = []