设计一个用户管理模块
Django提供了一个用户模型User,我们将在这个基础上设计用户管理模块。当然也可以自己设计,涉及到的认证和权限,请查看我的另一篇文章:https://blog.csdn.net/weixin_43431593/article/details/108930697
创建工程
File->New Project->选中Django,输入工程名称TestingPlatform直接创建。(专业版)
也可创建工程后手动创建,相关文章请查看本系列内容。(社区版)
连接数据库
1、登录mysql,创建数据库testing_platform:
CREATE DATABASE testing_platform CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
2、安装mysqlclient并连接mysql:
官网:https://pypi.org/project/mysqlclient/
官方描述:
Windows
Building mysqlclient on Windows is very hard. But there are some binary wheels you can install easily.
也就是在windows安装该模块比较困难,可能需要使用wheel安装:
虽然官方描述得比较艰难,但是,如果python版本正确的情况下(3.6、3.7、3.8),直接安装也是可以的:
pip install mysqlclient
3、连接数据库:
DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': BASE_DIR / 'db.sqlite3',
# }
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'testing_platform',
'USER': 'root',
'PASSWORD': 'yeqinfang',
# 'HOST': '192.168.31.201',
'HOST': '10.12.1.199',
'PORT': '3306',
}
}
执行迁移
python manage.py makemigrations
python manage.py migrate
如上,虽然没有创建应用,他也可以生成表,这些表就是django自带的表。我们将基于此进行用户管理的开发。
新建apps文件夹
如上,在工程文件下创建,与全局配置的文件夹平级。右键apps,将其标记为source root。
我想把所有应用放到apps文件夹,因为放在外面的话,后续应用会很多,不好管理。鉴于django是根据path路径来查找应用的,只要把路径添加到全局settings.py中即可:
sys.path.append(os.path.join(BASE_DIR, 'apps'))
创建应用
django-admin startapp user
创建user后,再把这个user应用拖动到apps中,不勾选任何选项。
注册应用
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'user',
]
注册rest_framework
先进行安装:
pip install djangorestframework
安装后,需要把它当做应用注册。
使用JWT认证方式
JWT 是一个开放标准(RFC 7519),它定义了一种用于简洁,自包含的用于通信双方之间以 JSON 对象的形式安全传递信息的方法。该信息可以被验证和信任,因为它是数字签名的。JWTS可以使用秘密(使用HMAC算法)或公钥/私钥对使用RSA或ECDSA来签名。
因为流行,所以我们先安装它,然后使用它:
pip install djangorestframework-jwt
编写用户管理接口
1、在user下创建序列化器serializers.py
2、基于django.contrib.auth.models的User模型编写序列化器:
from rest_framework import serializers
from rest_framework.validators import UniqueValidator
from django.contrib.auth.models import User
from rest_framework_jwt.serializers import jwt_payload_handler, jwt_encode_handler
class RegisterSerializer(serializers.ModelSerializer):
password_confirm = serializers.CharField(label='确认密码', help_text='确认密码',
min_length=6, max_length=20,
write_only=True,
error_messages={
'min_length': '仅允许6~20个字符的确认密码',
'max_length': '仅允许6~20个字符的确认密码', })
token = serializers.CharField(label='生成token', read_only=True)
class Meta:
model = User
fields = ('id', 'username', 'password', 'email', 'password_confirm', 'token')
extra_kwargs = {
'username': {
'label': '用户名',
'help_text': '用户名',
'min_length': 6,
'max_length': 20,
'error_messages': {
'min_length': '仅允许6-20个字符的用户名',
'max_length': '仅允许6-20个字符的用户名',
}
},
'email': {
'label': '邮箱',
'help_text': '邮箱',
'write_only': True,
'required': True,
# 添加邮箱重复校验
'validators': [UniqueValidator(queryset=User.objects.all(), message='此邮箱已注册')],
},
'password': {
'label': '密码',
'help_text': '密码',
'write_only': True,
'min_length': 6,
'max_length': 20,
'error_messages': {
'min_length': '仅允许6-20个字符的密码',
'max_length': '仅允许6-20个字符的密码',
}
}
}
def validate(self, attrs):
if attrs.get('password') != attrs.get('password_confirm'):
raise serializers.ValidationError('密码与确认密码不一致')
return attrs
def create(self, validated_data):
validated_data.pop('password_confirm')
# 创建user模型对象
user = User.objects.create_user(**validated_data)
# 创建token
payload = jwt_payload_handler(user)
token = jwt_encode_handler(payload)
user.token = token
return user
3、在视图中编写接口:
from django.contrib.auth.models import User
from rest_framework.views import APIView
from rest_framework.generics import CreateAPIView
from rest_framework.response import Response
from .serializers import RegisterSerializer
class UserView(CreateAPIView):
serializer_class = RegisterSerializer
# def post(self, request, *args, **kwargs):
# serializer = RegisterSerializer(data=request.data)
# serializer.is_valid(raise_exception=True)
# serializer.save()
#
# return Response(serializer.data, status=status.HTTP_201_CREATED)
class UsernameIsExistedView(APIView):
def get(self, request, username):
count = User.objects.filter(username=username).count()
# count = user.count()
one_dict = {
'username': username,
'count': count
}
return Response(one_dict)
class EmailIsExistedView(APIView):
def get(self, request, email):
count = User.objects.filter(email=email).count()
# count = user.count()
one_dict = {
'email': email,
'count': count
}
return Response(one_dict)
创建子路由
在user文件夹,新建一个urls,如:
from django.urls import path, re_path
from rest_framework_jwt.views import obtain_jwt_token
from . import views
urlpatterns = [
path('login/', obtain_jwt_token),
path('register/', views.UserView.as_view()),
re_path(r'^(?P<username>\w{6,20})/count/$', views.UsernameIsExistedView.as_view()),
re_path(r'^(?P<email>[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+)/count/$', views.EmailIsExistedView.as_view()),
]
注册子路由
在主路由中引用,举个例子:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('user/', include('user.urls')),
]
运行工程
python manage.py runserver
请求注册:
请求登录接口:
如上,说明注册接口和登录接口都已经实现,并且返回了JWT格式的token。
接口文档
安装依赖组件coreapi:
pip install coreapi
settings.py文件配置:
REST_FRAMEWORK = {
'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema'
}
主路由添加并使用:
from rest_framework.documentation import include_docs_urls
urlpatterns = [
path('admin/', admin.site.urls),
path('docs/', include_docs_urls(title='测试平台接口文档', description='xxx描述')),
path('user/', include('user.urls')),
]
再次运行后,打开界面如下:
JWT设置
上面的请求,并没有配置认证,因此,在工程目录下创建utils安装包目录,并写入:
def jwt_response_payload_handler(token, user=None, request=None):
return {
'user_id': user.id,
'username': user.username,
'token': token
}
该文件夹用于存储常用工具。
需要在settings配置:
REST_FRAMEWORK = {
'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',
'DEFAULT_AUTHENTICATION_CLASSES': [
# 指定使用JWT token认证方式
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
# 会话认证
'rest_framework.authentication.SessionAuthentication',
# 基本认证(用户名和密码认证)
'rest_framework.authentication.BasicAuthentication',
],
}
# 在全局配置JWT_AUTH中,可以覆盖JWT相关的参数
JWT_AUTH = {
# 指定处理登录接口响应数据的函数
'JWT_RESPONSE_PAYLOAD_HANDLER':
'utils.jwt_handle.jwt_response_payload_handler',
# 前端用户访问一些需要认证之后的接口,那么默认需要在请求头中携带参数,
# 请求key为Authorization,值为前缀 + 空格 + token值,如:JWT xxxssdhdsohsoshsohs
# 可以指定token过期时间,默认为5分钟
'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
# 指定前端传递token值的前缀
# 'JWT_AUTH_HEADER_PREFIX': 'Bearer',
}
先进行配置,后续我们写其他模块的时候,将会进行使用。接着运行起来,没有问题即可。