目前先實作使用者普通的使用者名密碼注冊、登入,後邊會改成第三方登入或短信驗證碼登入,其實都差不多。
model
使用者表包含了常用的基本資訊
# 使用者資訊表
class User(models.Model):
id = models.AutoField(primary_key=True)
username = models.CharField(max_length=32, unique=True, verbose_name='姓名', default='')
# gender_choices = ((0,'女'), (1, '男'), (-1, '無'))
gender = models.CharField(max_length=16, verbose_name='性别', default='未知')
age = models.PositiveIntegerField()
phone_number = models.CharField(max_length=16, unique=True, verbose_name='手機号')
email = models.EmailField(unique=True, verbose_name='郵箱')
password = models.CharField(max_length=64, verbose_name='密碼')
create_time = models.DateTimeField(auto_now_add=True)
update_time = models.DateTimeField(auto_now=True)
id_delete = models.BooleanField(default=False)
class meta:
db_table = 'user'
verbose_name = '使用者'
verbose_name_plural = '使用者'
def __str__(self):
return self.username
view
根據使用者登入名密碼進行驗證,驗證通過生成token傳回給使用者,以後請求需要攜帶token
from django.http import Http404
from django.shortcuts import render, HttpResponse, redirect
from django.views import View
from django.core.cache import cache
from rest_framework import viewsets, views
from rest_framework.response import Response
from .auth import LoginAuth
from .models import *
from .util import uuid4, pwd_hash, info, JwtToken
from .serializers import UserSerializer, UserRegSerializer
class Index(View):
def get(self, request):
dic = {
# 'uuid': 'eg',
'name': '張三',
'gender': 1,
'age': 24
}
print(uuid4())
obj = User.objects.create(**dic)
print(obj)
# raise Http404
return HttpResponse('index')
class Login(views.APIView):
# authentication_classes = [LoginAuth] # token驗證
# post請求
def post(self, request):
try:
data = request.data # 擷取接收的參數
password = data.pop('password') # 抽離出密碼
data['password'] = pwd_hash(password) # Hash密碼,不存儲明文密碼
user = User.objects.filter(**data,id_delete=False).values().first() # 查詢 沒有删除的使用者
user_ser = UserSerializer(data=user) # 序列化資料
user_ser.is_valid() # 序列化傳回值校驗
# 判斷是否存在該使用者
if user:
# 生成token
jwt_token = JwtToken()
token = jwt_token.encode_token(dict(user_ser.data))
# 将資料轉換成dict類型,并添加token到傳回資料中
data = dict(user_ser.data)
data['token'] = token
# 傳回資料
return info(data=data)
return info(status=0, message='使用者名或密碼錯誤')
except Exception as e:
return info(status=0, message='伺服器内部錯誤')
class UserView(viewsets.ModelViewSet):
queryset = User.objects.all().filter(id_delete=True)
serializer_class = UserSerializer
# def create(self, request, *args, **kwargs):
# print(request.data)
# serializer = self.get_serializer(data=request.data)
# serializer.is_valid(raise_exception=True)
# self.perform_create(serializer)
# headers = self.get_success_headers(serializer.data)
# return Response(serializer.data, headers=headers)
class Register(viewsets.ModelViewSet):
def create(self, request, *args, **kwargs):
try:
# 序列化資料
serializer = UserRegSerializer(data=request.data)
# 驗證資料,遇到錯誤主動抛出
if serializer.is_valid(raise_exception=True):
self.perform_create(serializer)
return info(data=serializer.data)
except Exception as e:
# 擷取參數
err = e.args[0]
if 'email' in err:
return info(message='使用者已注冊')
if 'phone_number' in err:
return info(message='手機号已注冊')
# 擷取缺少的字段
key = [k for k,v in err.items()]
return info(status=0, message='缺少字段' + str(key))
except:
return info(status=0, mes
serializers
from .models import *
from rest_framework import serializers, status
from .util import pwd_hash
import re
# 密碼驗證
def my_validate(val):
try:
re.search('[A-Z]+', val).group()
except:
raise serializers.ValidationError('密碼應包含大寫字母')
if len(val) < 8:
raise serializers.ValidationError('密碼應大于8位')
# return Response('密碼太短')
class UserSerializer(serializers.ModelSerializer):
def create(self, validated_data):
print(validated_data)
password = validated_data.pop('password')
validated_data['password'] = pwd_hash(password)
user_obj = User.objects.create(**validated_data)
return user_obj
class Meta:
model = User
fields = ['username', 'gender', 'age', 'phone_number', 'email', 'password']
extra_kwargs = {'password': {'write_only': True, "validators": [my_validate]}}
注冊
新使用者注冊
request參數
{
“username”: “李一三”,
“gender”: “男”,
“age”: “36”,
“phone_number”:“14395474448”,
“email”: “[email protected]”,
“password”: “1234567”
}
注冊成功會傳回注冊資訊
已經注冊過的使用者
傳回值
{
“status”: 1,
“message”: “使用者已注冊”,
“data”: “”
}
登入
驗證成功後的傳回值
{
"status": 1,
"message": "",
"data":{
"username": "李一",
"gender": "男",
"age": 36,
"phone_number": "14395974448",
"email": "[email protected]",
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJ1c2VybmFtZSI6ICJcdTY3NGVcdTRlMDAiLCAiZ2VuZGVyIjogIlx1NzUzNyIsICJhZ2UiOiAzNiwgInBob25lX251bWJlciI6ICIxNDM5NTk3NDQ0OCIsICJlbWFpbCI6ICJkaTg3MjkwOUAxMjYuY29tIiwgImlhdCI6IDE1ODgyMjY5ODMsICJleHAiOiAxNTg4MjMwNTgzfQ.Pg-xZfl17FtYWyimUdHKEnR19QbLBo5_DqLF3YmorCM0pTxA1wBMBwx4PXDL0htlHANpl-dss5C6SnBJ6qGBoxa-7Zva6lpUMDdZXHdBpGYvM7EL-r-xtf0K7HFIf-73oWkjvgfW5t1BHuijtItje6CmeyrlWG0DDANkddXjeQt57uTk1eGm-gZ6nX5EnhK0f_hPk5ok0JtVSCLWjjsHRyXLI4o3zT6VHhD8Cl7Mm5AWa1h3JeSmxbvcbvHSqZ21os94SVpzNLlqoVnRQPsTXFHcls_3_-vy6JY6o-ukMpuyEL6SAcz-kKeUn8VdlbmljjHY6VScV2a9i9r_LLDPGA"
}
}
登入錯誤傳回值
{
"status": 0,
"message": "使用者名或密碼錯誤",
"data": ""
}