django系列(一)之配置文件和日志介绍

"""
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,
        },
    },
}
posted @ 2026-04-07 14:17  有形无形  阅读(1)  评论(0)    收藏  举报