DRF --- 项目初始化
1. 基础配置
1.1 本地时区
settings.py
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
USE_TZ = False
1.2 静态目录
settings.py
STATIC_URL = 'static/'
STATICFILES_DIRS = (os.path.join(BASE_DIR, "static"),)
urls.py
from django.urls import re_path
from django.views.static import serve
from fileProject import settings
urlpatterns = [
	re_path(r"static/(?P<path>.*)", serve, {"document_root": settings.STATICFILES_DIRS}, name="static"),
]
1.3 文件上传存放目录
settings.py
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
urls.py
from django.urls import re_path
from django.views.static import serve
from fileProject import settings
urlpatterns = [
	re_path(r"media/(?P<path>.*)$", serve, {'document_root': settings.MEDIA_ROOT}, name="media"),
]
1.4 请求白名单
settings.py
ALLOWED_HOSTS = ["*"]
1.5 日志配置
settings.py
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            'format': '%(levelname)s %(asctime)s %(module)s %(lineno)d %(message)s'
        },
        'simple': {
            'format': '%(levelname)s %(module)s %(lineno)d %(message)s'
        },
    },
    'filters': {
        'require_debug_true': {
            '()': 'django.utils.log.RequireDebugTrue',
        },
    },
    'handlers': {
        'console': {
            'level': 'DEBUG',
            'filters': ['require_debug_true'],
            'class': 'logging.StreamHandler',
            'formatter': 'simple'
        },
        'file': {
            'level': 'ERROR',
            'class': 'logging.handlers.RotatingFileHandler',
            # 日志位置,日志文件名,日志保存目录必须手动创建
            'filename': os.path.join(os.path.dirname(os.path.join(BASE_DIR, "baler")), "logs/baler.log"),
            # 日志文件的最大值,这里我们设置300M
            'maxBytes': 300 * 1024 * 1024,
            # 日志文件的数量,设置最大日志数量为10
            'backupCount': 10,
            # 日志格式:详细格式
            'formatter': 'verbose',
            # 设置编码格式
            'encoding': 'utf-8'    
        },
    },
    # 日志对象
    'loggers': {
        'django': {
            'handlers': ['console', 'file'],
            'propagate': True,
        },
    }
}
2. 常用模块下载
requirements.py
PyMySQL==1.1.0
django-cors-headers==4.3.1
django-db-connection-pool==1.2.5
djangorestframework==3.15.1
djangorestframework-simplejwt==5.3.1
django-simpleui==2024.8.28
下载命令
pip install -r requirements.py -i https://mirrors.aliyun.com/pypi/simple
命令安装
pip install pymysql
pip install djangorestframework
pip install django-db-connection-pool
pip install djangorestframework-simplejwt
pip install django-cors-headers
pip install django-simpleui
3. 数据库配置
3.1 会话模式
settings.py
DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.mysql",
        "HOST": "127.0.0.1",
        "PORT": 3306,
        "USER": "luffy_user",
        "PASSWORD": "luffy",
        "NAME": "luffycity",
    }
}
项目根目录/__init__.py
import pymysql
pymysql.install_as_MySQLdb()
3.2 连接池模式
settings.py
DATABASES = {
    "default": {
        "ENGINE": "dj_db_conn_pool.backends.mysql",
        "HOST": "192.168.0.11",
        "PORT": "3306",
        "USER": "root",
        "PASSWORD": "vansing2022",
        "NAME": "station_control",
        "OPTIONS": {
            # 取消外键约束
            "init_command": "SET foreign_key_checks = 0;"
        },
        # 连接池配置参数
        'POOL_OPTIONS': {  
            'POOL_SIZE': 10,     # 连接池容量
            'MAX_OVERFLOW': 10,  # 连接池容量向上浮动最大值
            'RECYCLE': 30,       # 连接超时时间,如果设置为 -1 以外的值,则表示连接回收之间的秒数,这意味着在结帐时,如果超过此超时,则连接将关闭并替换为新打开的连接。默认为 -1。
        }
    }
}
参数分析
# 例如下面的配置,default 的连接池常规容量为10个连接,最大浮动10个, 即为:在 default 连接池创建后,随着程序对连接池的请求,连接池内连接将逐步增加到10个,如果在连接池内连接 全部用光后,程序又请求了第11个连接,此时的连接池容量将短暂超过 POOL_SIZE,但最大不超过 POOL_SIZE + MAX_OVERFLOW, 如果程序请求 default 数据库的连接数量超过 POOL_SIZE + MAX_OVERFLOW,那么连接池将一直等待直到程序释放连接, 请注意线程池对数据库连接池的使用,如果线程池大于连接池,且线程无主动释放连接的动作,可能会造成其他线程一直阻塞。
# POOL_SIZE(连接池容量)、MAX_OVERFLOW(连接池容量向上浮动最大值): 
这两个参数包含在 POOL_OPTIONS 内,例如下面的配置,default 的连接池常规容量为10个连接,最大浮动10个, 即为:在 default 连接池创建后,随着程序对连接池的请求,连接池内连接将逐步增加到10个,如果在连接池内连接 全部用光后,程序又请求了第11个连接,此时的连接池容量将短暂超过 POOL_SIZE,但最大不超过 POOL_SIZE + MAX_OVERFLOW, 如果程序请求 default 数据库的连接数量超过 POOL_SIZE + MAX_OVERFLOW,那么连接池将一直等待直到程序释放连接, 请注意线程池对数据库连接池的使用,如果线程池大于连接池,且线程无主动释放连接的动作,可能会造成其他线程一直阻塞。
# RECYCLE:
连接超时时间,如果设置为 -1 以外的值,则表示连接回收之间的秒数,这意味着在结帐时,如果超过此超时,则连接将关闭并替换为新打开的连接。默认为 -1。
4. 跨域配置
1. 注册应用
settings.py
INSTALLED_APPS = (
    ...
    'corsheaders',
    ...
)
2. 注册中间件
MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',   # 必须写在第一个位置
    ...
]
3. 添加跨域白名单
# 跨域白名单
CORS_ORIGIN_WHITELIST = (
    'www.luffycity.cn:8080',
)
CORS_ALLOW_CREDENTIALS = True  # 允许ajax跨域请求时携带cookie
# 如果想要所有请求都可以跨域
CORS_ORIGIN_ALLOW_ALL = True
# 允许跨域时携带的的 Header 类型
CORS_ALLOW_HEADERS = (
    "Appid", "Secret",
    "Access-Token",
    "token",
    "Content-Type",
    "Origin",
    "User-Agent",
    "DNT",
    "Cache-Control",
    "X-Requested-With"
)
# 或者直接设置为 *
CORS_ALLOW_HEADERS = ('*',)
5. restframework
settings.py
INSTALLED_APPS = [
    # ...
    'rest_framework',
    # ...
]
REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_simplejwt.authentication.JWTAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.BasicAuthentication',
    ),
}
6. simplejwt
settings.py
INSTALLED_APPS = [
    # ...
    'rest_framework_simplejwt',
    # ...
]
SIMPLE_JWT = {
    # token有效时长(返回的 access 有效时长)
    'ACCESS_TOKEN_LIFETIME': datetime.timedelta(days=5),
    # token刷新的有效时间(返回的 refresh 有效时长)
    'REFRESH_TOKEN_LIFETIME': datetime.timedelta(days=5),
    "TOKEN_OBTAIN_SERIALIZER": "user.serializers.MyTokenObtainPairSerializer",
}
xx.serializers.py 自定义校验成功的返回信息
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
    default_error_messages = {
        "code": 401,
        "err_msg": "token已失效",
    }
    default_code = 402
    '在荷载中添加自定义内容'
    @classmethod
    def get_token(cls, user):
        token = super().get_token(user)  # 签发用户
        token['name'] = user.username  # 往荷载里面添加用户名称
        return token
        '''重写get_token方法,它返回的token中就是荷载的内容'''
        '自定义返回格式'
    def validate(self, attrs):
        old_data = super().validate(attrs)
        data = {'code': 200,
                'msg': '登录成功',
                'username': self.user.username,
                'refresh': old_data['refresh'],
                'access': old_data['access']
                }
        return data
7. Django项目中集成Vue页面
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, "templates")],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
                "django.template.context_processors.media",
            ],
        },
    },
]
8. 跨域samesite配置
django中的samesite,为保留关键字,不允许私自调用set_cookie(),进行配置,只能在settings.py中配置,内容如下

8.1 版本高于2.1
CSRF_COOKIE_SECURE = True
CSRF_COOKIE_SAMESITE = 'None'
SESSION_COOKIE_SECURE = True
SESSION_COOKIE_SAMESITE = 'None'
8.2 版本低于2.1
1. 下载模块
pip install django-cookies-samesite
2. 将中间件添加到中间件类的顶部
MIDDLEWARE_CLASSES = (
    'django_cookies_samesite.middleware.CookiesSameSite',
    ...
)
3. 设置首选的samesite策略:
SESSION_COOKIE_SECURE = True
SESSION_COOKIE_SAMESITE = 'None'
注:必须同时有secure这个属性才行。是个坑!
9. 允许Django返回的页面内嵌页面(Iframe)
settings.py
X_FRAME_OPTIONS = "SAMEORIGIN"
10. 路由后缀校验模式
# 是否开启校验路由后缀
APPEND_SLASH=True
11. 初始化表结构
python .\manage.py migrate 
12. 创建超级用户
 python .\manage.py createsuperuser
13. simpleui 配置
0. 官方文档
https://newpanjing.github.io/simpleui_docs/config.html
1. 删除首页右侧的 simpleui 信息
{% if "SIMPLEUI_HOME_INFO"|get_config != False %}
<el-col :span="6">
    <el-card class="box-card">
        <div slot="header" class="clearfix">
            <span><i class="fab fa-stripe-s"></i>Simpleui <span
                                                                v-text="getLanuage('Home page')"></span></span>
            <el-button style="float: right; padding: 3px 0" type="text" @click="report()"><span
                                                                                                v-text="getLanuage('Report issue')"></span></el-button>
        </div>
        <div class="float-wrap clearfix">
            <div style="text-align: center">
                {% get_app_info %}
                <a v-if="upgrade.isUpdate" href="javascript:;" @click="upgrade.dialogVisible=true"
                   class="upgrade"><span class="el-icon-top"></span><span
                                                                          v-text="upgrade.version"></span></a>
            </div>
            <el-button icon="fas fa-code" @click="openUrl('https://gitee.com/tompeppa/simpleui')">Gitee
            </el-button>
            <el-button icon="fab fa-github" @click="openUrl('https://github.com/newpanjing/simpleui')">
                Github
            </el-button>
        </div>
    </el-card>
</el-col>
{% endif %}
2. 删除信息上报代码
admin/index.html
<!-- 336 行-->
{% load_analysis %}
site-packages/simpleui/templates/admin/index.html
<!-- 336 行-->
{% load_analysis %}
site-packages\simpleui\templatetags\simpletags.py
# 390 行
@register.simple_tag(takes_context=True)
def load_analysis(context):
    try:
        if not get_analysis_config():
            return ''
        # 理论上值一天只上报一次
        key = 'simpleui_' + time.strftime('%Y%m%d', time.localtime())
        if key in context.request.session:
            return ''
        b64 = ""
        j = {
            "n": platform.node(),
            "o": platform.platform(),
            "p": platform.python_version(),
            "d": django.get_version(),
            "s": simpleui.get_version(),
        }
        if 'theme_name' in context.request.COOKIES:
            j['t'] = context.request.COOKIES['theme_name']
        else:
            j['t'] = 'Default'
        b64 = base64.b64encode(str(j).encode('utf-8'))
        url = '//simpleui.72wo.com/analysis'
        b64 = b64.decode('utf-8')
        html = '<script async type="text/javascript" src="{}/{}"></script>'.format(url, b64);
        context.request.session[key] = True
        return mark_safe(html)
    except:
        return ''
3. 其他常用配置
SIMPLEUI_HOME_TITLE = "3D素材网"  # 首页名称
SIMPLEUI_HOME_PAGE = "https://www.baidu.com"  # 首页路径: 需要统一iframe
SIMPLEUI_HOME_ICON = 'fa fa-user'  # 首页图标
SIMPLEUI_INDEX = 'https://www.88cto.com' # 设置simpleui 点击首页图标跳转的地址
SIMPLEUI_LOGO = 'https://avatars2.githubusercontent.com/u/13655483?s=60&v=4  # 首页的标题logo
SIMPLEUI_HOME_INFO = False # 主页右侧的 simpleui 信息的展示与隐藏
SIMPLEUI_HOME_QUICK = False # 快捷操作的展示与隐藏
SIMPLEUI_HOME_ACTION = False  # 最近动作的展示与隐藏
SIMPLEUI_STATIC_OFFLINE = True  # 是否从第三方的 CDN 获取资源
SIMPLEUI_LOADING = False  # 是否加载遮罩层
4. 插件
1. django-import-expor
simpleui对数据导入导出插件也做了支持,您可以直接安装使用。
https://newpanjing.github.io/simpleui_docs/config.html#django-import-export
2. admindoc
admindoc需要simpleui 3.3+ 版本
https://newpanjing.github.io/simpleui_docs/config.html#admindoc
3. simplepro
simplepro也是我们推出的一个升级版的django admin插件,在现有的基础上,做了大量改进和优化。并且一前后分离的方式加载数据。
https://newpanjing.github.io/simpleui_docs/config.html#simplepro
14. 文件上传和 Admin 在线预览
models.py
class MaterialModels(models.Model):
    class Meta:
        verbose_name = "素材管理"
        verbose_name_plural = "素材管理"
    name = models.CharField("名称", max_length=64)
    file_path = models.FileField("素材文件", upload_to="materials/")
    def __str__(self):
        return self.name
settings.py
# 文件上传存放目录
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
url.py
from django.conf.urls.static import static
from SourceMaterial import settings
urlpatterns = [
    
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)  # 文件在线访问
    python防脱发技巧

                
            
        
浙公网安备 33010602011771号