I haven't updated many articles recently
It's really a little busy
I have been studying django rest framework, or drf for short
The development concept of drf conforms to the modern development concept
Front and rear split type
And I, Xiaobai, want to
Experience the process of front and back-end separated development
Although the leader of front-end and back-end separated development is java
But how can python join the fun
So I studied it
Because of the need for joint debugging, it is just a small function of registration
I've been debugging for about an hour, which is enough food-=-
No more nonsense, just go to the code
1. First look at our models
from django.contrib.auth.models import AbstractUser from django.db import models from django.utils import timezone class UserProfile(AbstractUser): """ user """ nickname = models.CharField(max_length=20, null=True, blank=True, verbose_name="nickname") mobile = models.CharField(max_length=11, null=True, blank=True, verbose_name="mobile phone") email = models.CharField(max_length=125, null=True, blank=True, verbose_name="mailbox") introduction = models.TextField(blank=True, null=True, verbose_name='brief introduction', default='The user was lazy and didn't write anything...') avatar = models.ImageField(upload_to='users/avatars/', null=True, blank=True, verbose_name='head portrait', default='') address = models.CharField(max_length=100, null=True, blank=True, verbose_name='User address', default='') birthday = models.DateField(verbose_name='birthday', blank=True, null=True, default=timezone.now) class Meta: verbose_name = "user" verbose_name_plural = verbose_name def __str__(self): return self.username def get_profile_name(self): if self.nickname: return self.nickname return self.username class VerifyCode(models.Model): """ SMS or email verification code """ code = models.CharField(max_length=10, verbose_name="Verification Code", default='') account = models.CharField(max_length=125, verbose_name="account number", default='') account_type = models.CharField(verbose_name="account type", choices=(("email", "mailbox"), ("mobile", "mobile phone")), default='email', max_length=6) add_time = models.DateTimeField(default=timezone.now, verbose_name="Add time") class Meta: verbose_name = "Verification Code" verbose_name_plural = verbose_name def __str__(self): return self.code
One user model, one verification code model
2.views view layer
from django.contrib.auth import get_user_model from django.contrib.auth.backends import ModelBackend from django.db.models import Q from django.shortcuts import render # Create your views here. from rest_framework.authtoken.views import ObtainAuthToken from rest_framework.authtoken.models import Token from rest_framework.response import Response from rest_framework import viewsets, mixins, status from rest_framework_jwt.serializers import jwt_payload_handler,jwt_encode_handler from .models import UserProfile from .models import VerifyCode from user.serializers import VerifySerializer, UserRegisterSerializer from utils.utils import send_verify_code_by_email,generate_code User=get_user_model() ··· class VerifyCodeViewset(mixins.CreateModelMixin,viewsets.GenericViewSet): """ Send email or mobile verification code """ serializer_class = VerifySerializer def create(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) account=serializer.validated_data['account'] account_type=serializer.validated_data['account_type'] verifycode=generate_code() if account_type =='email': send_status=send_verify_code_by_email(verifycode,[account,]) if send_status: #self.perform_create(serializer) vcode=VerifyCode(code=verifycode,account=account,account_type=account_type) vcode.save() headers = self.get_success_headers(serializer.data) return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) else: headers = self.get_success_headers(serializer.data) return Response(serializer.data, status=status.HTTP_400_BAD_REQUEST, headers=headers) else: pass class UserRegisterViewset(mixins.CreateModelMixin,viewsets.GenericViewSet): """User registration""" serializer_class = UserRegisterSerializer def create(self, request, *args, **kwargs): serializer=self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) user=self.perform_create(serializer) ret_data=serializer.data headers=self.get_success_headers(serializer.data) payload=jwt_payload_handler(user) token=jwt_encode_handler(payload) additional_data={'nickname':user.nickname,'userid':user.id,'token':token} ret_data.update(additional_data) return Response(ret_data,status=status.HTTP_201_CREATED,headers=headers) def perform_create(self, serializer): return serializer.save()
I don't think the code here is difficult to understand
It's mainly about this
serializer_class=
This sentence of code is to name the class to be serialized with
Of course, the class name behind this is self generated
Then write the code of the class
So I think this is the most important thing
Of course, the above two codes are simple create methods
3. Serialization class
from datetime import datetime,timedelta import re from django.contrib.auth import get_user_model from django.contrib.auth.hashers import make_password from django.db.models import Q from rest_framework import serializers from user.models import UserProfile,VerifyCode from .models import UserProfile User=get_user_model() ··· #Mobile number regular expression REGEX_MOBILE="^1[358]\d{9}$|^147\d{8}$|^176\d{8}$" class VerifySerializer(serializers.ModelSerializer): account_type=serializers.ChoiceField(choices=(("email","mailbox"),("mobile","mobile phone")),help_text='account type') account=serializers.CharField(max_length=125,help_text="account number") # def validate_account(self, account): # print(account) def validate(self, attrs): accountType=attrs['account_type'] account=attrs['account'] #Judge whether the account is registered if User.objects.filter(Q(mobile=account)|Q(email=account)).first(): raise serializers.ValidationError("User already exists") if accountType=='mobile': #Verify whether the mobile phone number is legal if not re.match(REGEX_MOBILE,account): raise serializers.ValidationError("Illegal mobile phone number") return attrs class Meta: model=VerifyCode fields=['account','account_type'] class UserRegisterSerializer(serializers.ModelSerializer): account = serializers.CharField(required=True,write_only=True,max_length=125, help_text="account number") account_type = serializers.ChoiceField(required=True,write_only=True,choices=(("email", "mailbox"), ("mobile", "mobile phone")), help_text='account type') code=serializers.CharField(required=True,write_only=True,max_length=4,min_length=4,label="Verification Code", error_messages={'blank':'Please enter the verification code','required':'Verification code is required'}) """User registered serialization class""" def validate_code(self,code): account=self.initial_data['account'] account_type=self.initial_data['account_type'] existed=VerifyCode.objects.filter(account_type=account_type,account=account).order_by('-add_time') if existed: last_record=existed[0] five_mintes_ago=datetime.now()-timedelta(hours=0,minutes=5,seconds=0) if last_record.code!=code: raise serializers.ValidationError("sorry:( Verification code error") if five_mintes_ago>last_record.add_time: raise serializers.ValidationError("sorry:( Verification code expired") else: raise serializers.ValidationError("sorry:( Verification code does not exist") def validate(self, attrs): accountType=attrs['account_type'] if accountType=='email': attrs['email']=attrs['account'] if accountType=='mobile': attrs['mobile']=attrs['account'] attrs['nickname']=attrs['username'] attrs['password']=make_password(attrs['password']) del attrs['code'] del attrs['account_type'] del attrs['account'] return attrs class Meta: model=UserProfile fields=['username','account','account_type','code','password']
ok, the above is the code of the most important serialization class
Let me make a few comments
among
VerifySerializer
Is a serialized class that sends verification codes
The function is to obtain the verification code. You can choose whether to register by email or mobile phone
Then get the corresponding verification code
I took a look at the price of the mobile phone verification code
I couldn't help but cry
It costs four cents a piece
It's still a goose farm. Hey, it's not equipped with mobile phone registration for the time being
But we haven't studied the registration of mobile verification code yet
The second class,
UserRegisterSerializer
This is the complete registration class
The verification information is legal, then the verification code is sent, and then check whether the verification code is expired or invalid
wait
One of the most important things to talk about by name is this small parameter
write_only=True
You can find it in the code
Let me talk about the function directly. If this code is added, the attributes of the model in which this code is located will not be serialized by drf, and thus the corresponding objects will not be generated
Maybe you're a little dizzy. Let me explain this. In 1, we don't have the attribute of account in our user model, that is, UserProfile. However, when we send the verification code when registering, we must need the attribute of account, because the system can only send you the verification code when we know your account, whether it's phone or email
However, when serializing and generating UserProfile, we do not need the attribute account
Right
So we need to add
write_only=True
In this way, the front end also has an account, and the back end can also send verification codes
It can also avoid 500
Because when I didn't add it, the browser reported an error of 500
Later, I studied it according to the error information
It's its pot
It's her, it's her, our little Nezha!
Finally, put a picture of the front end
The front end uses vue+iview
The project is almost finished, and the rest is to publish blogs and personal centers
Why should I write this article today? Because it's really hard to register-=-
Especially the JWT with the front and rear ends separated
so,I finally figure it out
Then good night
Let's use another expression bag from the previous article
