1. 当前位置:网站首页 > Python

Django初始化相机及登录注册基础功能集成开发


产品中台项目

环境说明

基于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",
}


本文最后更新于2021-4-2,已超过 3个月没有更新,如果文章内容或图片资源失效,请留言反馈,我们会及时处理,谢谢!
版权说明

本文地址:http://www.liuyangdeboke.cn/?post=26
未标注转载均为本站远程,转载请注明文章出处:

发表评论

联系我们

在线咨询:点击这里给我发消息

微信号:17721538135

工作日:9:00-23:00,节假日休息

扫码关注