DRF — write a login interface, which can be accessed without login or login with the same interface

Time:2021-8-26

requirement:

Write login interfaces. An interface can be accessed without login or login (anonymous users access once a minute and login users access three times a minute)
#The student and user tables are required

1.models.py

from django.db import models

class Student(models.Model):
    name = models.CharField(max_length=32)
    Sex = models. Smallintegerfield (choices = ((1, 'male'), (2, 'female'), (3, 'unknown'), 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, 'super user'), (2, 'ordinary user'), (3, 'two users'), default = 1)
#This table can be combined with the user table, but it is decoupled and has high scalability
class UserToken(models.Model):
    user = models.OneToOneField(to='User',on_delete=models.CASCADE)
    token = models.CharField(max_length=64)

2. Data migration, two commands; Then connect to the database and write the test data in the user and student tables

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: # no logged in user
            return self.get_ Ident (request) # according to IP restrictions
        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': 'login succeeded'}
        username = request.data.get('username')
        password = request.data.get('password')
        #Query database
        user = models.User.objects.filter(username=username, password=password).first()

        if user:
            Token = UUID. Uuid4() # generates a random string
            #Save the token in the usertoken table (if it is the first login: add; if it is not the first login: update)
            models.UserToken.objects.update_or_create(defaults={'token': token}, user=user)
            res['token'] = token
            return Response(res)
        else:
            res['code'] = 101
            Res ['msg '] =' wrong user name or password '

            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
#Automatic route generation
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'
    }
}

 

follow-up:

If you want to write two interfaces, one interface does not log in and access once, and the other interface logs in and accesses three times, you can use the following methods: (it is recommended to write two interfaces to decouple, so there is no need to write so much judgment trouble)
-Mode 1:
        -Write two frequency classes (one based on IP limit and the other based on userid)
-Mode 2:
        -Use the built-in. If you can, you can have no problem. If there is a problem, you need to inherit and rewrite get_ cache_ Key method