产品中台项目
环境说明
基于Ubuntu20.04 python3.8.10 Django3.2.8 djangorestframework3.13.1开发
前端采用vue3 ElementPlus TypeScript
数据库mysql root liu123456789
安装步骤
pip3 install django==3.2.8 -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
pip3 install mysqlclient==2.1.1 -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
pip3 install Pillow==7.0.0 -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
pip3 install djangorestframework==3.13.1 -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
pip3 install djangorestframework-jwt -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
django-admin startproject product
cd product
修改app目录下setting.py
修改时区
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
修改为
LANGUAGE_CODE = 'zh-Hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
USE_TZ = False
修改数据库(sqlite修改为 mysql)
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': BASE_DIR / 'db.sqlite3', } } 修改为 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'HOST': '127.0.0.1', 'PORT': 3306, 'USER': 'root', 'PASSWORD': 'liu123456789', 'NAME': 'product_center' } }
注释CSRF中间件,使用新的跨域解析
MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', # 用来解决跨域问题 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', # 'django.middleware.csrf.CsrfViewMiddleware', # 解决跨越CSRF token问题 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ]
增加允许所有地址访问适配
ALLOWED_HOSTS = [] 修改为 ALLOWED_HOSTS = ['*']
新建app user
python3 manage.py startapp api
setting.py注册
INSTALLED_APPS = [
'django.contrib.admin', # 站台管理系统
'django.contrib.auth', # 认证系统
'django.contrib.contenttypes', # content type框架
'django.contrib.sessions', # session框架
'django.contrib.messages', # message框架
'django.contrib.staticfiles', # 静态文件管理框架
'api', # 新增
]
运行
python3 manage.py runserver 0.0.0.0:8190
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
July 12, 2022 - 10:24:53
Django version 3.2.8, using settings 'product.settings'
Starting development server at http://0.0.0.0:8190/
Quit the server with CONTROL-C.
增加restful插件
修改setting.py
INSTALLED_APPS = [
'django.contrib.admin', # 站台管理系统
'django.contrib.auth', # 认证系统
'django.contrib.contenttypes', # content type框架
'django.contrib.sessions', # session框架
'django.contrib.messages', # message框架
'django.contrib.staticfiles', # 静态文件管理框架
'rest_framework', # restful插件
'rest_framework.authtoken', # 鉴权组件
'api', # 新增
]
集成自定义用户校验模块
在setting.py最后追加
# 设置自定义鉴权
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication',
),
# 权限后端,有多个权限后端,默认遵循最严格的那个
'DEFAULT_PERMISSION_CLASSES': (
# 以下4种控制方式,根据实际情况开启一种即可
'rest_framework.permissions.IsAuthenticated', # 只有经过身份验证的用户才能访问
# 'rest_framework.permissions.IsAdminUser', # 允许管理员,即is_staff=True才能访问
# 'rest_framework.permissions.AllowAny', # 允许任何人,包括匿名用户
# 'rest_framework.permissions.IsAuthenticatedOrReadOnly', # 认证,或者只读
),
}
JWT_AUTH = {
'JWT_RESPONSE_PAYLOAD_HANDLER':
'api.views.jwt_response_payload_handler',
'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
}
创建超级用户
python3 manage.py makemigrations
python3 manage.py migrate
python3 manage.py createsuperuser
建一个超级管理员
新建路由
在api下新建urls.py
from django.urls import path
from . import views
urlpatterns = [
path('signIn', obtain_jwt_token), # 登录
path('register', views.Register.as_view())
]
在project目录下修改urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('api.urls'))
]
在api目录下新建序列文件serializers.py
from rest_framework import serializers,validators
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': [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个字符的密码',
}
}
}
# 多字段校验:直接使用validate,但是必须返回attrs
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
在api目录下修改views.py 编写注册方法【这里得log目录和文件需要新建mkdir新建,否则会出错,也可以写异常自动建文件方法了】
import logging
from rest_framework import generics
from api.serializers import RegisterSerializer
from rest_framework.permissions import IsAdminUser
# 生成一个以当前文件名为名字的logger实例
logger = logging.getLogger(__name__)
def jwt_response_payload_handler(token, user, request):
# 重载登录接口
return {
'token': token,
'username': user.username,
'user_id': user.id,
}
class Register(generics.CreateAPIView):
permission_classes = [IsAdminUser]
# noinspection PyBroadException
try:
serializer_class = RegisterSerializer
except Exception as e:
logger.warning("注册接口发生了一个错误 %s" % e)
在api目录下修改views.py新建登录方法
集成错误日志功能
setting.py中尾部追加
# 日志配置
BASE_LOG_DIR = os.path.join(BASE_DIR, "log")
LOGGING = {
'version': 1,
'disable_existing_loggers': False, # 禁用已经存在的logger实例
# 日志文件的格式
'formatters': {
'standard': {'format': '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]'
'[%(levelname)s][%(message)s]'},
'simple': {'format': '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'},
'collect': {'format': '%(message)s'}
},
# 过滤器
'filters': {
'require_debug_true': {'()': 'django.utils.log.RequireDebugTrue',},
},
# 处理器
'handlers': {
# 在终端打印
'console': {
'level': 'DEBUG',
'filters': ['require_debug_true'], # 只有在Django debug为True时才在屏幕打印日志
'class': 'logging.StreamHandler', #
'formatter': 'simple'
},
# 默认的
'default': {
'level': 'INFO',
'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,自动切
'filename': os.path.join(BASE_LOG_DIR, "product_info.log"), # 日志文件
'maxBytes': 1024 * 1024 * 50, # 日志大小 50M
'backupCount': 2, # 最多备份几个
'formatter': 'standard',
'encoding': 'utf-8',
},
# 专门用来记错误日志
'error': {
'level': 'ERROR',
'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,自动切
'filename': os.path.join(BASE_LOG_DIR, "product_err.log"), # 日志文件
'maxBytes': 1024 * 1024 * 50, # 日志大小 50M
'backupCount': 3,
'formatter': 'standard',
'encoding': 'utf-8',
},
# 专门定义一个收集特定信息的日志
'collect': {
'level': 'INFO',
'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,自动切
'filename': os.path.join(BASE_LOG_DIR, "product_collect.log"),
'maxBytes': 1024 * 1024 * 50, # 日志大小 50M
'backupCount': 3,
'formatter': 'collect',
'encoding': 'utf-8',
}
},
'loggers': {
# 默认的logger应用如下配置
'': {
'handlers': ['default', 'console', 'error'], # 上线之后可以把console移除
'level': 'DEBUG',
'propagate': True, # 向不向更高级别的logger传递
},
# 名为 collect的logger还单独处理
'collect': {
'handlers': ['console', 'collect'],
'level': 'INFO',
}
},
}
views.py中使用(示例)
import logging
# 生成一个以当前文件名为名字的logger实例
logger = logging.getLogger(__name__)
# 生成一个名为collect的logger实例
collect_logger = logging.getLogger("collect")
def index(request):
logger.debug("一个萌萌的请求过来了。。。。")
logger.info("一个更萌的请求过来了。。。。")
logger.debug("这是app01里面的index视图函数")
collect_logger.info("用户1:河南")
return HttpResponse("OK")
备注
登录请求地址及参数
http://192.168.30.26:8190/api/signIn
multipart/form-data
username = 创建的超级用户
password = 创建的超级密码
注册(如果使用非管理员token会提示没有权限)
http://192.168.30.26:8190/api/register
application/json
heder头里得加入jwt校验负责不生效
Authorization JWT xxxxxx
参数
{
"username": "test1234",
"email":"",
"password": "pg123456",
"password_confirm": "pg123456",
}
本文地址:http://www.liuyangdeboke.cn/?post=26
未标注转载均为本站远程,转载请注明文章出处:
发表评论