基本步驟:
一侨赡、自定義用戶表:
1冷蚂、自定義的用戶表繼承AbstractUser覆旱;
2骇塘、settings.py添加配置伊履,指向用戶表:AUTH_USER_MODEL = 'myUser.Account'(子項目名稱.用戶表models名稱);
3款违、python manage.py makemigrations
4唐瀑、python manage.py migrate
二、自定義登錄驗證:
# 簽發(fā):
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
# 生成token:
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
三插爹、獲取當(dāng)前登錄用戶:
# 通過headers獲取token:
token = request.META.get('HTTP_AUTHORIZATION')
# 情況一:token的傳參格式為JWT xxxx
token = request.META.get('HTTP_AUTHORIZATION')[4:]
# 情況二:token的傳參格式為TOKEN xxxx
token = request.META.get('HTTP_AUTHORIZATION')[7:]
# 然后解析出user_id和username:
jwt_decode_handler = api_settings.JWT_DECODE_HANDLER
-
基本目錄結(jié)構(gòu)
話不多說哄辣,直接上代碼
- models:
from django.db import models
from django.contrib.auth.models import AbstractUser
"""
基類:可以把通用的字段定義這里,其他地方繼承基類即可擁有
"""
class BaseModel(models.Model):
updated_tm = models.DateTimeField(auto_now=True)
created_tm = models.DateTimeField(auto_now_add=True)
class Meta:
abstract = True
"""
用戶表:自定義的用戶表
想要使用自定義的用戶表進行登錄驗證赠尾,需要滿足下面的條件:
1力穗、需要繼承AbstractUser;
2气嫁、settings.py添加配置:AUTH_USER_MODEL = 'myUser.Account'(子項目名稱.用戶表models名稱)
"""
class Account(AbstractUser, BaseModel):
user_id = models.AutoField(help_text="用戶id", primary_key=True)
username = models.SlugField(max_length=128, help_text="用戶名", unique=True)
password = models.CharField(max_length=128, help_text="用戶密碼")
nickname = models.CharField(max_length=128, help_text="用戶昵稱")
# 指定數(shù)據(jù)庫表信息
class Meta:
db_table = 'user'
verbose_name = '用戶基礎(chǔ)信息'
verbose_name_plural = verbose_name
"""
項目表:重點關(guān)注editor字段
"""
class ProjectList(BaseModel):
"""項目基本信息"""
project_id = models.AutoField(help_text="項目id", primary_key=True)
project_name = models.SlugField(max_length=128, help_text="項目名", unique=True)
editor = models.CharField(max_length=128, default='admin', help_text="編輯者")
class Meta:
db_table = 'project'
verbose_name = '項目基本信息'
verbose_name_plural = verbose_name
- 自定義用戶數(shù)據(jù)庫表
- serializers
from rest_framework import serializers
from myUser.models import BaseModel, Account
from myProject.models import ProjectList
import time
class BaseSerializer(serializers.ModelSerializer):
"""基類序列化器"""
create_tm_format = serializers.DateTimeField(source="created_tm",
format="%Y-%m-%d %H:%M:%S",
required=False,
read_only=True,
help_text='創(chuàng)建時間(北京時間)')
update_tm_format = serializers.DateTimeField(source="updated_tm",
format="%Y-%m-%d %H:%M:%S",
required=False,
read_only=True,
help_text='更新時間(北京時間)')
created_tm = serializers.DateTimeField(required=False,
read_only=True,
help_text='創(chuàng)建時間(時間戳)')
updated_tm = serializers.DateTimeField(required=False,
read_only=True,
help_text='更新時間(時間戳)')
class Meta:
model = BaseModel
fields = ("created_tm", "updated_tm",
"create_tm_format", "update_tm_format")
class UserSerializer(BaseSerializer):
"""用戶基本信息"""
user_id = serializers.IntegerField(read_only=True)
class Meta:
model = Account
fields = ('username', 'password', 'user_id')
class ProjectListSerializer(BaseSerializer):
"""項目基本信息"""
class Meta:
model = ProjectList
fields = ('project_id', 'project_name', 'editor',
'created_start_tm', 'created_end_tm',
"created_tm", "updated_tm")
- filter
import django_filters
from myUser.models import Account
from myProject.models import ProjectList
class UserFilter(django_filters.rest_framework.FilterSet):
"""用戶基本信息"""
user_id = django_filters.NumberFilter(field_name='user_id', lookup_expr='exact')
username = django_filters.CharFilter(field_name='username', lookup_expr='icontains')
nickname = django_filters.CharFilter(field_name='nickname', lookup_expr='icontains')
created_start_tm = django_filters.DateTimeFromToRangeFilter(field_name='創(chuàng)建開始時間')
created_end_tm = django_filters.DateTimeFromToRangeFilter(field_name='創(chuàng)建結(jié)束時間')
class Meta:
model = Account
fields = ('user_id', 'username', 'created_start_tm', 'created_end_tm')
class ProjectListFilter(django_filters.rest_framework.FilterSet):
"""項目基本信息"""
project_id = django_filters.NumberFilter(field_name='project_id', lookup_expr='exact')
project_name = django_filters.CharFilter(field_name='project_name', lookup_expr='icontains')
editor = django_filters.CharFilter(field_name='editor', lookup_expr='exact')
created_start_tm = django_filters.DateTimeFromToRangeFilter(field_name='創(chuàng)建開始時間')
created_end_tm = django_filters.DateTimeFromToRangeFilter(field_name='創(chuàng)建結(jié)束時間')
class Meta:
model = ProjectList
fields = ('project_id', 'project_name', 'created_start_tm', 'created_end_tm')
- 用戶登錄views
from drf_yasg.utils import swagger_auto_schema
from myUser.models import Account
from rest_framework import mixins
from rest_framework.generics import GenericAPIView
from serializers import UserSerializer
from render_response import APIResponse
from rest_framework_jwt.settings import api_settings
# 簽發(fā)
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
# 生成token
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
# Create your views here.
class LoginView(mixins.UpdateModelMixin, GenericAPIView):
authentication_classes = ()
permission_classes = ()
queryset = Account.objects.all()
serializer_class = UserSerializer
ordering = ['-created_tm']
tag = ['用戶']
@swagger_auto_schema(tags=tag,
operation_id="login",
operation_summary='用戶登錄',
operation_description='明文密碼',
responses={400010: "賬號密碼錯誤", 200: UserSerializer})
def post(self, request, *args, **kwargs):
"""
post: 用戶登錄
400010:賬號密碼錯誤
"""
username = str(request.data.get('username'))
password = str(request.data.get('password'))
try:
Account.objects.get(username=username)
except Account.DoesNotExist:
return APIResponse(400010, '賬號密碼錯誤', success=False)
try:
Account.objects.get(password=password, username=username)
except Account.DoesNotExist:
return APIResponse(400010, '賬號密碼錯誤', success=False)
user = Account.objects.filter(username=username, password=password).first()
if user:
# 登錄成功当窗,簽發(fā)token,通過當(dāng)前登錄用戶獲取荷載(payload)
payload = jwt_payload_handler(user)
# 通過payload生成token串(三段:頭,payload寸宵,簽名)
token = jwt_encode_handler(payload)
response = {"user_id": user.user_id, "username": username, "token": token}
return APIResponse(200, '登錄成功', response)
- 項目創(chuàng)建views
from drf_yasg.utils import swagger_auto_schema
from myProject.models import ProjectList
from rest_framework import mixins
from rest_framework.viewsets import GenericViewSet
from serializers import ProjectListSerializer
from render_response import APIResponse
from rest_framework.response import Response
from get_login_user_info import GetLoginUser
# Create your views here.
class AddProjectViews(mixins.CreateModelMixin, GenericViewSet):
authentication_classes = []
permission_classes = ()
queryset = ProjectList.objects.all().order_by("-created_tm")
serializer_class = ProjectListSerializer
tag = ['項目']
@swagger_auto_schema(tags=tag,
operation_summary='創(chuàng)建項目',
operation_id="project_create",
operation_description='項目名稱必填',
responses={400014: "參數(shù)錯誤",
200: ProjectListSerializer,
400013: "請檢查輸入字段是否正確(必填字段崖面、未定義字段)",
500001: "項目名稱長度需要1到20位",
500002: "項目已存在",
500003: "項目創(chuàng)建失敗", })
def create(self, request, *args, **kwargs):
"""新增項目"""
try:
project_name = request.data.get("project_name")
project_desc = request.data.get("project_desc")
except Exception:
return APIResponse(400014, '參數(shù)錯誤', success=False)
field_list = {}
if project_name:
field_list["project_name"] = project_name
if project_desc:
field_list["project_desc"] = project_desc
# 獲取當(dāng)前登錄用戶信息
user = GetLoginUser().get_login_user(request)
if user["code"] == 200:
field_list["editor"] = user["username"]
else:
return Response(user)
# 檢查賬號密碼是否有填寫
if "project_name" not in list(field_list.keys()):
return APIResponse(400013, '請檢查輸入字段是否正確(必填字段、未定義字段)', success=False)
else:
if len(field_list["project_name"]) > 20 or len(field_list["project_name"]) < 1:
return APIResponse(500001, '項目名稱長度需要1到20位', success=False)
try:
ProjectList.objects.get(project_name=field_list["project_name"])
return APIResponse(500002, '項目已存在', success=False)
except ProjectList.DoesNotExist:
try:
ProjectList.objects.create(**field_list)
return APIResponse(200, '項目創(chuàng)建成功')
except Exception as e:
print(e)
return APIResponse(500003, '項目創(chuàng)建失敗', success=False)
- token的傳參
- 返回我是這么定義的(來自網(wǎng)友)
"""
自定義返回處理
"""
from rest_framework.response import Response
class APIResponse(Response):
def __init__(self, code=200, msg='請求成功', data=None, status=None, headers=None, success=True, **kwargs):
dic = {'code': code, 'message': msg, 'success': success, 'data': None}
if data:
dic['data'] = data
dic.update(kwargs) # 可以靈活的添加梯影,需要返回的鍵值對
super().__init__(data=dic, status=status, headers=headers)
- 獲取當(dāng)前登錄用戶信息我是這么寫的(原創(chuàng))
from myUser.models import Account
from jwt import ExpiredSignatureError
from render_response import APIResponse
from rest_framework_jwt.settings import api_settings
# 解析token
jwt_decode_handler = api_settings.JWT_DECODE_HANDLER
class GetLoginUser:
@staticmethod
def get_login_user(request):
try:
token = request.META.get('HTTP_AUTHORIZATION')
except Exception:
return APIResponse(400014, '參數(shù)錯誤', success=False)
if token:
try:
# 解密token巫员,提取user_id
user_id = jwt_decode_handler(token)["user_id"]
username = Account.objects.filter(user_id=user_id).values('username').first()
return {"user_id": user_id, "username": username["username"], "code": 200}
except ExpiredSignatureError:
return APIResponse(4031, 'token已過期', success=False)
else:
return APIResponse(403, '無訪問權(quán)限,請重新登錄或稍后再試光酣!', success=False)
-
簡易的swagger文檔
-
用戶登錄
項目創(chuàng)建