天天看點

Django實作微信商城小程式後端-注冊與登入

目前先實作使用者普通的使用者名密碼注冊、登入,後邊會改成第三方登入或短信驗證碼登入,其實都差不多。

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": ""
}
           
下一篇: 第六章-習題