要求:編寫登錄接口,,一個(gè)接口既可以不登錄訪問(wèn),又可以登錄訪問(wèn)(匿名用戶一分鐘訪問(wèn)1次,登錄用戶一分鐘訪問(wèn)3次)
#需要用到student和user表
1.models.py from django.db import models class Student(models.Model): name = models.CharField(max_length=32) sex = models.SmallIntegerField(choices=((1, '男'), (2, '女'), (3, '未知')), default=1) age = models.IntegerField() class User(models.Model): username = models.CharField(max_length=32) password = models.CharField(max_length=32) user_type = models.IntegerField(choices=((1, '超級(jí)用戶'), (2, '普通用戶'), (3, '二筆用戶')),default=1) #此表完全可以與User表合為一個(gè),,但這樣解耦合,,可擴(kuò)展性高 class UserToken(models.Model): user = models.OneToOneField(to='User',on_delete=models.CASCADE) token = models.CharField(max_length=64) 2.數(shù)據(jù)遷移,兩條命令,;然后連接數(shù)據(jù)庫(kù),,在user和student表中寫入測(cè)試數(shù)據(jù) 3.serializer.py from rest_framework import serializers from app01.models import Student class StudentSerializer(serializers.ModelSerializer): sex = serializers.CharField(source='get_sex_display') class Meta: model = Student fields = '__all__' 4.auth.py from rest_framework.throttling import BaseThrottle,SimpleRateThrottle from app01 import models #from rest_framework.exceptions import AuthenticationFailed from rest_framework.authentication import BaseAuthentication class LoginAuth(BaseAuthentication): def authenticate(self, request): token = request.GET.get('token') res = models.UserToken.objects.filter(token=token).first() if res: return (res.user, token) else: return None class MySimpleThrottle(SimpleRateThrottle): scope = 'xxx' def get_cache_key(self, request, view): if not request.user.id: # 沒(méi)有登錄用戶 return self.get_ident(request) # 根據(jù)ip限制 else: return None class MyLoginThrottle(SimpleRateThrottle): scope = 'login' def get_cache_key(self, request, view): return request.user.pk 5.views.py from rest_framework.views import APIView from app01 import models import uuid from app01.auth import LoginAuth,MyLoginThrottle,MySimpleThrottle class LoginView(APIView): authentication_classes = [] def post(self, request): res = {'code': 100, 'msg': '登錄成功'} username = request.data.get('username') password = request.data.get('password') # 查詢數(shù)據(jù)庫(kù) user = models.User.objects.filter(username=username, password=password).first() if user: token = uuid.uuid4() # 生成一個(gè)隨機(jī)字符串 # 把token存到UserToken表中(如果是第一次登錄:新增,如果不是第一次:更新) models.UserToken.objects.update_or_create(defaults={'token': token}, user=user) res['token'] = token return Response(res) else: res['code'] = 101 res['msg'] = '用戶名或密碼錯(cuò)誤' return Response(res) from app01.models import Student from app01.serializer import StudentSerializer from rest_framework.mixins import ListModelMixin from rest_framework.viewsets import GenericViewSet from rest_framework.response import Response from rest_framework.mixins import CreateModelMixin class StudentView(GenericViewSet, ListModelMixin, CreateModelMixin): queryset = Student.objects.all() serializer_class = StudentSerializer authentication_classes = [LoginAuth,] throttle_classes = [MyLoginThrottle,MySimpleThrottle,] 6.urls.py from django.urls import path from app01 import views #自動(dòng)生成路由 from rest_framework.routers import SimpleRouter router=SimpleRouter() router.register('students',views.StudentView) urlpatterns = [ path('login/', views.LoginView.as_view()), ] urlpatterns+=router.urls print(router.urls) 7.settings.py INSTALLED_APPS = [ ... 'rest_framework' ] REST_FRAMEWORK = { # 'DEFAULT_THROTTLE_CLASSES':['app01.auth.MyThrottle',], 'DEFAULT_THROTTLE_RATES' : { 'xxx':'1/m', 'login':'3/m' } }
后續(xù):如果要寫兩個(gè)接口,,一個(gè)接口不登陸訪問(wèn)1次,,一個(gè)接口登錄訪問(wèn)3次,可以用以下的方式:(推薦使用寫兩個(gè)接口,,這樣解耦合,,不需要寫那么多判斷麻煩) -方式一: -寫兩個(gè)頻率類(一個(gè)是根據(jù)ip限制,另一個(gè)根據(jù)userid) -方式二: -使用內(nèi)置的,,如果可以,,就沒(méi)問(wèn)題就可以,如果又問(wèn)題需要繼承重寫get_cache_key方法
|
|