
1. Django日志配置基础与实战在Django开发中日志记录是项目维护和调试的重要工具。与简单的print()语句相比专业的日志系统可以提供更结构化的信息输出和更灵活的控制方式。让我们从最基础的配置开始逐步构建一个适合生产环境的日志系统。1.1 日志系统核心组件解析Django的日志系统建立在Python标准库的logging模块之上包含四个关键组件Loggers日志入口点每个logger对应一个命名空间Handlers决定日志记录的输出目的地Filters提供额外的日志过滤控制Formatters指定日志输出的最终格式一个典型的日志记录流程是Logger → Filter → Handler → Formatter → 输出目标。理解这个流程对配置日志系统至关重要。1.2 基础配置示例下面是一个最基本的日志配置将日志输出到控制台# settings.py LOGGING { version: 1, disable_existing_loggers: False, handlers: { console: { class: logging.StreamHandler, }, }, root: { handlers: [console], level: INFO, }, }这个配置做了以下几件事使用dictConfig格式版本1不禁用现有的logger保留Django默认logger定义一个名为console的StreamHandler配置根logger使用console handler日志级别为INFO提示disable_existing_loggers参数需要特别注意。设置为True会禁用所有已存在的logger包括Django内置的这通常不是我们想要的行为。1.3 按模块区分日志级别在实际项目中我们通常需要对不同模块设置不同的日志级别。例如我们可能希望Django核心模块输出WARNING级别日志而我们自己的应用模块输出DEBUG级别日志LOGGING { version: 1, disable_existing_loggers: False, handlers: { console: { class: logging.StreamHandler, }, }, loggers: { django: { handlers: [console], level: WARNING, propagate: False, }, myapp: { handlers: [console], level: DEBUG, propagate: False, }, }, }这里有几个关键点我们分别为django和myapp配置了不同的日志级别propagateFalse表示日志不会传递给父logger如果没有匹配的logger配置日志将被根logger处理1.4 日志文件输出配置生产环境中我们通常需要将日志写入文件而非控制台。下面是一个将日志写入文件的配置示例LOGGING { version: 1, disable_existing_loggers: False, handlers: { file: { level: DEBUG, class: logging.FileHandler, filename: /var/log/django/debug.log, formatter: verbose, }, }, formatters: { verbose: { format: {levelname} {asctime} {module} {process:d} {thread:d} {message}, style: {, }, }, loggers: { django: { handlers: [file], level: INFO, propagate: True, }, }, }实际部署时需要注意确保Django进程对日志文件路径有写入权限考虑使用RotatingFileHandler或TimedRotatingFileHandler来避免日志文件过大生产环境应避免使用DEBUG级别因为它会产生大量日志2. 高级日志配置与最佳实践2.1 多处理器配置在实际项目中我们通常需要根据日志级别将日志分发到不同的目的地。例如INFO及以上级别日志写入文件ERROR级别日志发送邮件通知LOGGING { version: 1, disable_existing_loggers: False, formatters: { standard: { format: %(asctime)s [%(levelname)s] %(name)s: %(message)s }, }, handlers: { file: { level: INFO, class: logging.handlers.RotatingFileHandler, filename: /var/log/django/app.log, maxBytes: 1024*1024*5, # 5MB backupCount: 5, formatter: standard }, mail_admins: { level: ERROR, class: django.utils.log.AdminEmailHandler, include_html: False, } }, loggers: { django: { handlers: [file, mail_admins], level: INFO, propagate: False, }, }, }2.2 日志过滤与敏感信息处理日志中可能包含敏感信息如用户凭证、个人信息等我们需要特别注意from django.utils.log import RequireDebugFalse LOGGING { version: 1, filters: { require_debug_false: { (): RequireDebugFalse, }, filter_sensitive_data: { (): myapp.logging.SensitiveDataFilter, }, }, handlers: { console: { class: logging.StreamHandler, filters: [filter_sensitive_data], }, }, # ...其他配置 }可以创建自定义过滤器来移除敏感信息# myapp/logging.py import logging class SensitiveDataFilter(logging.Filter): def filter(self, record): if hasattr(record, msg): record.msg self._clean_data(record.msg) return True def _clean_data(self, message): # 实现敏感信息替换逻辑 return message.replace(password123456, password******)2.3 结构化日志记录对于复杂系统结构化日志如JSON格式更易于分析和处理LOGGING { version: 1, formatters: { json: { (): pythonjsonlogger.jsonlogger.JsonFormatter, fmt: %(asctime)s %(levelname)s %(name)s %(message)s } }, handlers: { console: { class: logging.StreamHandler, formatter: json } }, # ...其他配置 }需要先安装python-json-logger包pip install python-json-logger2.4 日志性能优化不当的日志配置可能影响应用性能以下是一些优化建议避免在生产环境使用DEBUG级别对于高频日志考虑使用logging.handlers.QueueHandler和logging.handlers.QueueListener实现异步日志谨慎使用include_htmlTrue的AdminEmailHandler它会产生大量数据使用propagateFalse避免重复日志处理3. Django调试工具栏深度配置3.1 安装与基本配置Django Debug Toolbar是开发阶段的利器安装步骤如下pip install django-debug-toolbar然后在settings.py中配置INSTALLED_APPS [ # ... debug_toolbar, # ... ] MIDDLEWARE [ # ... debug_toolbar.middleware.DebugToolbarMiddleware, # ... ] INTERNAL_IPS [127.0.0.1]对于Docker开发环境需要额外配置import socket hostname, _, ips socket.gethostbyname_ex(socket.gethostname()) INTERNAL_IPS [ip[:-1] 1 for ip in ips] [127.0.0.1]3.2 工具栏面板配置Debug Toolbar由多个面板组成可以根据需要启用/禁用DEBUG_TOOLBAR_PANELS [ debug_toolbar.panels.history.HistoryPanel, debug_toolbar.panels.versions.VersionsPanel, debug_toolbar.panels.timer.TimerPanel, debug_toolbar.panels.settings.SettingsPanel, debug_toolbar.panels.headers.HeadersPanel, debug_toolbar.panels.request.RequestPanel, debug_toolbar.panels.sql.SQLPanel, debug_toolbar.panels.staticfiles.StaticFilesPanel, debug_toolbar.panels.templates.TemplatesPanel, debug_toolbar.panels.cache.CachePanel, debug_toolbar.panels.signals.SignalsPanel, debug_toolbar.panels.logging.LoggingPanel, debug_toolbar.panels.redirects.RedirectsPanel, debug_toolbar.panels.profiling.ProfilingPanel, ]3.3 SQL查询分析与优化SQL面板是调试工具栏中最有用的功能之一它显示每个页面加载执行的所有SQL查询每个查询的执行时间查询的调用堆栈EXPLAIN结果MySQL/PostgreSQL优化建议查找重复查询 - 可能提示需要添加select_related/prefetch_related关注耗时长的查询 - 可能需要添加索引或重写查询检查查询数量 - N1问题的典型表现是查询数量随列表项增加而线性增长3.4 模板调试技巧模板面板显示使用的所有模板及其加载路径模板渲染时间上下文变量调试技巧查找重复加载的模板识别渲染时间过长的模板检查上下文变量是否包含意外的大量数据3.5 自定义面板开发当内置面板不满足需求时可以创建自定义面板# myapp/debug_panels.py from debug_toolbar.panels import Panel class MyCustomPanel(Panel): title Custom Panel def generate_stats(self, request, response): self.record_stats({ custom_data: request.META.get(HTTP_USER_AGENT, Unknown) }) # settings.py DEBUG_TOOLBAR_PANELS [ # ... myapp.debug_panels.MyCustomPanel, # ... ]4. Django ORM高级优化实践4.1 查询优化基础Django ORM虽然方便但容易产生性能问题。以下是一些基础优化技巧使用select_related优化外键查询# 不好的做法 - 每个author都会产生额外查询 books Book.objects.all() for book in books: print(book.author.name) # 好的做法 - 使用select_related一次性获取关联数据 books Book.objects.select_related(author).all()使用prefetch_related优化多对多关系# 不好的做法 categories Category.objects.all() for category in categories: print([book.title for book in category.books.all()]) # 好的做法 categories Category.objects.prefetch_related(books).all()只获取需要的字段# 不好的做法 - 获取所有字段 books Book.objects.all() # 好的做法 - 只获取需要的字段 books Book.objects.only(title, author__name)4.2 高级查询技巧批量操作# 批量创建 Book.objects.bulk_create([ Book(titleBook 1), Book(titleBook 2) ]) # 批量更新 books Book.objects.filter(publishedTrue) books.update(statuspublished)使用F()表达式避免竞态条件from django.db.models import F # 不是线程安全的 product Product.objects.get(id1) product.stock - 1 product.save() # 线程安全的方式 Product.objects.filter(id1).update(stockF(stock) - 1)使用annotate和aggregatefrom django.db.models import Count, Avg # 每个作者的书本数 authors Author.objects.annotate(book_countCount(books)) # 所有书本的平均价格 avg_price Book.objects.aggregate(Avg(price))4.3 数据库索引优化合理的数据库索引可以大幅提升查询性能为常用查询条件添加db_indexclass Book(models.Model): title models.CharField(max_length100, db_indexTrue) published_date models.DateField(db_indexTrue)对于多字段组合查询使用index_togetherclass Meta: index_together [ (title, published_date), ]考虑使用GinIndex对复杂查询进行优化PostgreSQLfrom django.contrib.postgres.indexes import GinIndex class Book(models.Model): class Meta: indexes [ GinIndex(fields[title], nametitle_gin_idx), ]4.4 ORM性能分析工具使用django-silk进行性能分析pip install django-silk配置settings.pyINSTALLED_APPS [ ... silk, ] MIDDLEWARE [ ... silk.middleware.SilkyMiddleware, ]使用django-extensions的shell_plus和runserver_pluspip install django-extensions这些工具提供了增强的shell和开发服务器包含自动加载和更好的调试功能。使用EXPLAIN分析查询# 在Django shell中 from django.db import connection books Book.objects.filter(title__startswithD) print(connection.queries[-1][sql]) # 然后可以在数据库客户端中执行EXPLAIN ANALYZE [上面的SQL]5. 综合实战构建优化型开发环境5.1 项目日志架构设计一个完整项目的日志系统应该考虑以下方面开发环境控制台输出详细格式包含文件行号DEBUG级别生产环境文件输出带日志轮转JSON格式便于日志收集系统处理WARNING及以上级别错误报警邮件/Sentry等示例配置# settings/logging.py import os from pathlib import Path BASE_DIR Path(__file__).resolve().parent.parent def get_logging_config(debug): handlers { console: { level: DEBUG, class: logging.StreamHandler, formatter: verbose, }, file: { level: INFO, class: logging.handlers.RotatingFileHandler, filename: BASE_DIR / logs / django.log, maxBytes: 1024 * 1024 * 5, # 5MB backupCount: 5, formatter: json, }, } if not debug: handlers[mail_admins] { level: ERROR, class: django.utils.log.AdminEmailHandler, include_html: False, } return { version: 1, disable_existing_loggers: False, formatters: { verbose: { format: %(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s }, json: { (): pythonjsonlogger.jsonlogger.JsonFormatter, fmt: %(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s }, }, handlers: handlers, loggers: { django: { handlers: [console, file], level: DEBUG if debug else INFO, propagate: False, }, myapp: { handlers: [console, file], level: DEBUG if debug else INFO, propagate: False, }, }, } # settings.py DEBUG True # 或 False LOGGING get_logging_config(DEBUG)5.2 开发-生产环境差异化配置使用环境变量管理不同环境的配置差异# settings.py import os from .logging import get_logging_config DEBUG os.getenv(DJANGO_DEBUG, False) True LOGGING get_logging_config(DEBUG) # Debug Toolbar配置 if DEBUG: INSTALLED_APPS [debug_toolbar] MIDDLEWARE.insert(0, debug_toolbar.middleware.DebugToolbarMiddleware) INTERNAL_IPS [127.0.0.1] # 配置数据库查询日志 LOGGING[loggers][django.db.backends] { handlers: [console], level: DEBUG, propagate: False, }5.3 自动化测试中的日志配置测试环境需要特殊的日志配置# settings/test.py from .base import * LOGGING { version: 1, disable_existing_loggers: False, handlers: { null: { class: logging.NullHandler, }, }, loggers: { django: { handlers: [null], level: CRITICAL, propagate: False, }, }, }这样配置可以避免测试输出被日志淹没提高测试运行速度对于需要测试日志的情况可以针对特定测试用例临时修改日志配置5.4 监控与报警集成生产环境应该集成专业的监控系统Sentry集成pip install sentry-sdkimport sentry_sdk from sentry_sdk.integrations.django import DjangoIntegration sentry_sdk.init( dsnyour-dsn-here, integrations[DjangoIntegration()], traces_sample_rate1.0, send_default_piiTrue )性能监控如New Relic或Datadog# New Relic配置 NEW_RELIC_CONFIG_FILE /path/to/newrelic.ini if os.path.exists(NEW_RELIC_CONFIG_FILE): import newrelic.agent newrelic.agent.initialize(NEW_RELIC_CONFIG_FILE) application newrelic.agent.wsgi_application()(get_wsgi_application())健康检查端点# urls.py from django.urls import path from django.http import JsonResponse def health_check(request): return JsonResponse({status: ok}) urlpatterns [ path(health/, health_check), # ...其他URL ]6. 常见问题与解决方案6.1 日志不工作的常见原因LOGGING_CONFIG设置被覆盖 检查是否有代码修改了LOGGING_CONFIG或调用了logging.config.dictConfigdisable_existing_loggersTrue 这会导致Django内置logger被禁用日志级别设置过高 确保logger和handler的级别允许你的日志消息通过权限问题 检查进程是否有写入日志文件的权限6.2 Debug Toolbar不显示的排查步骤检查DEBUGTrue确认INTERNAL_IPS包含你的IP检查MIDDLEWARE顺序DebugToolbarMiddleware应尽可能靠前查看HTML响应底部是否有工具栏的HTML注释检查浏览器控制台是否有JavaScript错误6.3 ORM性能问题诊断识别N1查询问题 使用Debug Toolbar或django-silk检查查询数量分析慢查询使用connection.queries查看原始SQL在数据库中使用EXPLAIN ANALYZE索引缺失检查使用./manage.py check --deploy检查常见配置问题使用数据库特定工具如PostgreSQL的pg_stat_statements识别高频查询6.4 生产环境调试技巧受限调试# 在视图中临时启用调试 from django.views.decorators.debug import sensitive_variables sensitive_variables(user_password) def my_view(request): if request.user.is_superuser: debug_toolbar.show_toolbar True # ...安全日志记录# 记录异常但不暴露敏感信息 import logging logger logging.getLogger(__name__) try: # 可能出错的代码 except Exception as e: logger.error(处理订单时出错: %s, str(e), exc_infoTrue, extra{ order_id: order.id, user_id: request.user.id })性能分析中间件# 用于临时分析生产环境性能问题 class ProfilerMiddleware: def __init__(self, get_response): self.get_response get_response def __call__(self, request): if request.GET.get(profile): import cProfile profiler cProfile.Profile() profiler.enable() response self.get_response(request) if request.GET.get(profile): profiler.disable() profiler.dump_stats(/tmp/profile.stats) return response通过系统性地应用这些日志配置、调试工具和ORM优化技术可以显著提升Django应用的开发效率和运行性能。记住良好的日志实践和性能优化应该从项目开始时就考虑而不是等到出现问题后才补救。