"""
Django settings for djangoProject project.
Generated by 'django-admin startproject' using Django 5.0.1.
For more information on this file, see
https://docs.djangoproject.com/en/5.0/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/5.0/ref/settings/
"""
from pathlib import Path
# Build paths inside the project like this: BASE_DIR / 'subdir'.
# __file__代表的是当前文件,即settings.py文件,那么Path(__file__).resolve()的结果将会是settings.py文件的绝对路径;
# 然后parent取其父目录,两个parent就是向上两层父级目录 ,也就是django-admin创建项目之后的路径。
BASE_DIR = Path(__file__).resolve().parent.parent
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
# SECRET_KEY:密钥,项目中默认的一些加密用它(不需要关注,可以改,但是不能删)
SECRET_KEY = 'django-insecure-%=raz$qe%sh4f(3(_q#6av&*y=vew&4tv$e6_r8fq(lmud4z#l'
# SECURITY WARNING: don't run with debug turned on in production!
# DEBUG:调试模式,开发阶段是true, 开报错信息更完善,上线阶段把它设成false,不然会泄露项目的关键信息
DEBUG = True
# ALLOWED_HOSTS:上线阶段使用,允许谁访问
# 例如 ALLOWED_HOSTS = ['*']
ALLOWED_HOSTS = []
# Application definition
# 项目所有的app,新建的app要在里面注册
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01.apps.App01Config',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 开启csrf验证
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
# ROOT_URLCONF 根路由是哪个文件,根路由的位置可以变
ROOT_URLCONF = 'djangoProject.urls'
# 模板文件存放路径,项目中 templates 模版目录可以放在项目容器下面,也可以放在每个app里面,
TEMPLATES = [
{
# 指定模板引擎,django.template.backends.django.DjangoTemplates(默认,Django 内置引擎)
'BACKEND': 'django.template.backends.django.DjangoTemplates',
# 模板文件的搜索路径(列表形式,可添加多个目录),如果这里不配置,为空[],则不会到根目录下的templates里寻找模版,只会到每个app下的templates里寻找
# 这里查找顺序是先在根目录下查找,找不到再按 INSTALLED_APPS 的注册顺序,遍历每个 app 下的templates目录查找
# 如果渲染页面时,指定目录,则只会到该目录下查找,比如render(request, 'app1/templates/app1/index.html')
'DIRS': [BASE_DIR / 'templates'] # 项目根目录下的templates文件夹。这里要配置,一些全局的模版要放在这里
# 是否在各app目录下的templates文件夹中搜索模板
'APP_DIRS': True,
'OPTIONS': {
# 上下文处理器(可在所有模板中直接使用的变量)
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request', # 重要:提供request变量
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
# 当渲染模板时,Django 会按以下顺序查找:
# 先搜索 DIRS 中配置的目录(全局模板)
# 再搜索各 app 下的 templates 目录(按 INSTALLED_APPS 中的顺序)
# 'DIRS': [] 如果dir配置为空,则直接搜索app下的templates 目录
# WSGI_APPLICATION wsgi服务器使用的是哪个
WSGI_APPLICATION = 'djangoProject.wsgi.application'
# Database
# https://docs.djangoproject.com/en/5.0/ref/settings/#databases
# 数据库连接配置
# DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': BASE_DIR / 'db.sqlite3',
# }
# }
# 下面是数据库的设置,这里直接改成我们在djangoProject/__init__.py里设置好的mysql数据库,按如下配置就可以了,
# 依次是数据库引擎(mysql还是oracle还是pg或者别的数据库),数据库名称,用户名,密码,主机,端口,按前面配置的来就行。
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'django',
'USER': 'root',
'PASSWORD': '',
'HOST': '192.168.167.xxx',
'PORT': '3306',
}
}
"""
上面的数据库配置是基本配置项,还有一些配置项(可选):
AUTOCOMMIT:
默认: True
如果你想 禁用 Django 的事务管理 并实现你自己的事务管理,请将此设置为 False
CONN_MAX_AGE:
默认: 0
一个数据库连接的寿命,以秒为整数。使用 0 在每次请求结束时关闭数据库连接——这是 Django 的默认行为,使用 None 则是无限的持久连接。
OPTIONS:
默认: {} (空字典)
连接到数据库时要使用的额外参数,比如 ssl、init_command 和 sql_mode、隔离级别等。可用的参数根据你的数据库后端不同而不同。
"""
# 数据库全部参数,上面是配置了必须的参数,其余采用默认值
# DATABASES = {'default': {'ATOMIC_REQUESTS': False,
# 'AUTOCOMMIT': True,
# 'CONN_HEALTH_CHECKS': False,
# 'CONN_MAX_AGE': 0,
# 'ENGINE': 'django.db.backends.mysql',
# 'HOST': '192.168.167.150',
# 'NAME': 'django',
# 'OPTIONS': {},
# 'PASSWORD': '********************',
# 'PORT': '3306',
# 'TEST': {'CHARSET': None,
# 'COLLATION': None,
# 'MIGRATE': True,
# 'MIRROR': None,
# 'NAME': None},
# 'TIME_ZONE': None,
# 'USER': 'root'}}
# Password validation
# https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validators
# 用于检查用户密码强度的验证器列表。不用管(内置app相关)
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/5.0/topics/i18n/
# 国际化相关,语言,时区
# 设置的是django后台管理相关的语言时区等
LANGUAGE_CODE = 'zh-hans' # zh-hans:中文 en-us:英文
TIME_ZONE = 'Asia/Shanghai' # Asia/Shanghai UTC
# 用于指定是否应该启用 Django 的翻译系统。
USE_I18N = True
# 用于指定 Django 是否默认使用时区感知。
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/5.0/howto/static-files/
# 静态文件(CSS/JS/ 静态图片)访问路径前缀,这里django默认生成的是相对路径,但这是历史遗留问题,django建议配置成绝对路径
STATIC_URL = 'static/' # 相对路径,默认
STATIC_URL = '/static/' # 绝对路径,改成这样
# 媒体文件(头像、附件、上传的图片等)的URL访问前缀(前端访问用)
# 生产环境中,禁止用此方式(性能差),需通过 Nginx/Apache 直接托管 MEDIA_ROOT 目录
MEDIA_URL = '/media/'
# 静态文件存储路径,只需要配置全局的static文件夹即可,不需要配置每个app下的static文件夹,django会自动去app下寻找
# 查找顺序是先按「INSTALLED_APPS 中 app 的顺序」查各 app 的静态目录,找到就停止,不会继续向下查找,最后找不到才去根目录下查找
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static')
# os.path.join(BASE_DIR, 'vms/static') # 这个不需要,配也不会有问题,但是不需要
]
# 生产环境中,执行collectstatic命令后收集所有静态文件之后,存放的路径,开发环境中,django会自动寻找静态文件,无需执行collectstatic命令
STATIC_ROOT = os.path.join('BASE_DIR', 'staticfiles')
# Django 会将用户上传的文件保存到该目录下
MEDIA_ROOT = os.path.join(BASE_DIR, 'media') # 推荐:项目根目录下的media文件夹
# Default primary key field type
# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field
# 默认的主键字段类型,用于没有带 primary_key=True 字段的模型。
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
# 日志配置
# ===================== 日志目录创建 =====================
LOG_DIR = os.path.join(BASE_DIR, 'log')
os.makedirs(LOG_DIR, exist_ok=True) # 自动创建日志目录(不存在时)
# ===================== 核心日志配置 =====================
LOGGING = {
'version': 1,
'disable_existing_loggers': False, # 不禁用其他已存在的 logger,django默认有些自己的 logger,如django,django.request等
'formatters': { # 定义了几种格式的日志,供下面的handle选择使用
# 详细日志格式,包含堆栈信息,适合trace.log
'verbose': {
# name是Logger 的名称, module是python文件名,不含.py
'format': '{asctime} {levelname} {module} {process:d} {thread:d} {message}', # 代码里打印日志时必须带上exc_info=True,否则不会输出堆栈信息
'style': '{', # 声明用大括号占位符,例如{levelname} 是大括号包裹,还可以用%s占位符
"datefmt": "%Y-%m-%d %H:%M:%S",
},
# 简单日志格式
'simple': {
'format': '{levelname} {message}',
'style': '{',
},
# 业务日志格式:侧重业务语义,无技术细节
"business": {
"format": "[{asctime}] {levelname} {name} {module}.{funcName}:{lineno} - {message}",
"style": "{",
"datefmt": "%Y-%m-%d %H:%M:%S",
},
},
"""
handle中class参数介绍
1、定义:class 参数用于指定日志处理器的具体实现类,决定了日志消息的输出目标和处理方式(比如输出到文件、控制台、邮件等)。
不同的class对应不同的日志处理逻辑,是日志配置中控制 “日志往哪存 / 怎么存” 的核心参数。
2、基础的处理器类
logging.FileHandler:将日志写到文件
logging.StreamHandler:将日志输出到 “流”(通常是控制台 / 终端,也可指定其他流)
3、扩展处理器类(除了基础处理器类,Django 还支持更实用的扩展处理器类,更常用)
logging.handlers.RotatingFileHandler:按文件大小轮转日志(比如文件达到 10MB 时自动新建文件),避免单文件过大,适合生产环境:
'class': 'logging.handlers.RotatingFileHandler',
'maxBytes': 10485760, # 每个日志文件10MB
'backupCount': 10, # 保留10个日志文件
logging.handlers.TimedRotatingFileHandler:按时间轮转日志(比如每天 / 每周生成新文件),便于按时间归档日志:
'class': 'logging.handlers.TimedRotatingFileHandler',
'when': 'D', # 按天轮转(可选S/秒、M/分、H/时、D/天、W0-6/周)
'backupCount': 30, # 保留30天的日志,如果上面是H,那就是保留30小时的日志,以此类推
logging.handlers.SMTPHandler:将关键错误日志发送到指定邮箱(如系统崩溃时邮件告警):
'class': 'logging.handlers.SMTPHandler',
'mailhost': ('smtp.example.com', 587),
'fromaddr': 'server@example.com',
'toaddrs': ['admin@example.com'],
'subject': 'Django项目错误告警',
'credentials': ('user', 'password'),
"""
'handlers': {
'prod_file': { # 生产环境日志处理器
'level': 'WARNING',
'class': 'logging.handlers.TimedRotatingFileHandler',
'when': 'D', # 按天轮转(可选S/秒、M/分、H/时、D/天、W0-6/周)
'backupCount': 30,
'filename': os.path.join(LOG_DIR, 'django_error.log'), # 错误日志文件路径
'formatter': 'verbose',
'encoding': 'utf-8',
},
'dev_console': { # 开发环境日志处理器
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'verbose',
},
"business_file": { # 业务日志处理器(生产/开发通用)
"level": "INFO",
"class": "logging.handlers.TimedRotatingFileHandler", # 按时间轮转
"filename": os.path.join(LOG_DIR , "business.log"), # 业务日志文件路径
"when": "D", # 每天轮转
"backupCount": 30, # 保留30天
"encoding": "utf-8",
"formatter": "business",
},
"mail": { # 严重错误邮件告警(生产),可选
"level": "ERROR",
"class": "django.utils.log.AdminEmailHandler",
"formatter": "verbose",
"include_html": False, # 不发送HTML格式,避免泄露细节
},
},
"""
root:根日志器(全局默认日志器)
root是所有日志器的 “祖先”,是日志系统的顶层入口。如果某个日志请求没有匹配到任何自定义日志器(如django、myapp),
就会使用root的配置处理日志。
"""
'root': {
'handlers': ['dev_console'] if DEBUG else ['prod_file'],
'level': 'WARNING', # 加上这行,过滤掉第三方库的 DEBUG/INFO
},
"""
loggers:自定义日志器(按模块 / 功能分类)
loggers字典里的django、myapp是日志器的名字,用于为不同模块 / 应用设置独立的日志规则(比如不同的级别、输出目标)。
比如'django'日志器专门处理 Django 框架内部的日志(如 ORM、中间件的日志);
'myapp'日志器专门处理你自己项目中myapp应用的业务日志。也可以为每个app都设置自己的logger,实现更精细化的日志控制
注意:如果你的代码中捕获了异常但未重新抛出(如try-except包裹了Model.save()但没处理),
Django 是无法自动捕获异常并将其写入日志的。这种情况需要在except块中手动记录日志 或者raise 主动抛出异常
"""
'loggers': {
# ---------------- Django核心日志器 ----------------
'django': { # django框架核心日志器
'handlers': ['dev_console'] if DEBUG else ['prod_file'], # 使用上面定义的处理器,可以选多个或一个
'level': 'DEBUG' if DEBUG else 'ERROR', # 日志过滤是 loggers里的 + console里的双重过滤,先logger,再console
'propagate': False, # 日志传播开关,当前日志器处理完日志后,是否将日志向上传递给父级日志器再处理一遍(包括root)
},
"django.request": { # HTTP请求日志(4xx/5xx)
"handlers": ["dev_console"] if DEBUG else ["prod_file"],
"level": "DEBUG" if DEBUG else "ERROR",
"propagate": False,
},
"django.db.backends": { # 数据库日志
"handlers": ["dev_console"] if DEBUG else ["prod_file"],
"level": "DEBUG" if DEBUG else "WARNING",
"propagate": False,
},
"django.security": {
"handlers": ["dev_console"] if DEBUG else ["prod_file"],
"level": "DEBUG" if DEBUG else "WARNING",
"propagate": False,
},
# ---------------- 业务日志器,可以为每个app都配置一个单独的,实现精细化的日志管理,也可以共用这一个 ----------------
'your_app': { # 你自己的app所使用的logger,代码里 import logging logger = logging.getLogger('your_app')就可以使用了
'handlers': ['business_file'],
'level': 'INFO',
'propagate': False,
},
},
}