Skip to content

Django基础概念

本章将深入介绍Django的核心概念,包括项目设置、应用配置、中间件系统、信号机制等,帮助你全面理解Django框架的工作原理。

Django项目架构

MVT架构模式

Django采用MVT (Model-View-Template) 架构模式,这是对传统MVC模式的变体:

┌─────────────────────────────────────────────────────────┐
│                    Django MVT 架构                       │
├─────────────────────────────────────────────────────────┤
│  HTTP请求 → URL路由 → 视图(View) → 模型(Model)          │
│                        ↓              ↓                │
│                   模板(Template) ← 数据处理              │
│                        ↓                                │
│                   HTTP响应 → 客户端                     │
└─────────────────────────────────────────────────────────┘

Model (模型)

  • 定义数据结构和业务逻辑
  • 与数据库交互
  • 数据验证和处理

View (视图)

  • 处理HTTP请求
  • 业务逻辑控制
  • 调用模型和模板

Template (模板)

  • 表现层逻辑
  • HTML生成
  • 数据展示

请求-响应流程

python
# 1. URL路由匹配
# urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('articles/<int:id>/', views.article_detail, name='article_detail'),
]

# 2. 视图处理请求
# views.py
from django.shortcuts import render, get_object_or_404
from .models import Article

def article_detail(request, id):
    article = get_object_or_404(Article, id=id)
    return render(request, 'articles/detail.html', {'article': article})

# 3. 模型数据查询
# models.py
from django.db import models

class Article(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    
    def __str__(self):
        return self.title

# 4. 模板渲染
# templates/articles/detail.html
<h1>{{ article.title }}</h1>
<p>{{ article.content }}</p>
<small>发布时间: {{ article.created_at }}</small>

Django设置系统

设置文件结构

python
# settings.py 的基本结构
import os
from pathlib import Path

# 项目根目录
BASE_DIR = Path(__file__).resolve().parent.parent

# 核心设置
DEBUG = True
SECRET_KEY = 'your-secret-key'
ALLOWED_HOSTS = []

# 应用程序
INSTALLED_APPS = [
    # Django内置应用
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    
    # 第三方应用
    'rest_framework',
    'debug_toolbar',
    
    # 本地应用
    'blog.apps.BlogConfig',
    'accounts.apps.AccountsConfig',
]

# 中间件
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

# URL配置
ROOT_URLCONF = 'mysite.urls'

# 数据库
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}
```##
# 重要设置详解

#### DEBUG设置

```python
# 开发环境
DEBUG = True
ALLOWED_HOSTS = []  # 空列表表示只允许localhost

# 生产环境
DEBUG = False
ALLOWED_HOSTS = ['yourdomain.com', 'www.yourdomain.com']

# DEBUG=True时的特性
- 详细的错误页面
- 自动重载代码
- 静态文件自动服务
- SQL查询调试信息

# DEBUG=False时的要求
- 必须设置ALLOWED_HOSTS
- 需要配置静态文件服务
- 错误信息被隐藏
- 性能优化启用

SECRET_KEY设置

python
# 生成安全的密钥
from django.core.management.utils import get_random_secret_key
SECRET_KEY = get_random_secret_key()

# 从环境变量读取
import os
SECRET_KEY = os.environ.get('SECRET_KEY')

# 使用python-decouple
from decouple import config
SECRET_KEY = config('SECRET_KEY')

# SECRET_KEY的用途
- CSRF令牌生成
- 会话签名
- 密码重置令牌
- 其他加密操作

数据库配置

python
# SQLite配置(开发环境)
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}

# PostgreSQL配置(推荐生产环境)
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'mydatabase',
        'USER': 'mydatabaseuser',
        'PASSWORD': 'mypassword',
        'HOST': '127.0.0.1',
        'PORT': '5432',
        'OPTIONS': {
            'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
        },
    }
}

# MySQL配置
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'mydatabase',
        'USER': 'mydatabaseuser',
        'PASSWORD': 'mypassword',
        'HOST': '127.0.0.1',
        'PORT': '3306',
        'OPTIONS': {
            'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
        },
    }
}

# 多数据库配置
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'main_db',
        'USER': 'postgres',
        'PASSWORD': 'password',
        'HOST': 'localhost',
        'PORT': '5432',
    },
    'users_db': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'users_db',
        'USER': 'mysql_user',
        'PASSWORD': 'mysql_password',
        'HOST': 'localhost',
        'PORT': '3306',
    }
}

# 数据库路由
DATABASE_ROUTERS = ['mysite.routers.DatabaseRouter']

应用配置系统

AppConfig类

python
# apps.py
from django.apps import AppConfig

class BlogConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'blog'
    verbose_name = '博客管理'
    
    def ready(self):
        """应用准备就绪时调用"""
        # 导入信号处理器
        import blog.signals
        
        # 执行初始化代码
        self.setup_logging()
    
    def setup_logging(self):
        """设置日志配置"""
        import logging
        logger = logging.getLogger(__name__)
        logger.info(f'{self.verbose_name} 应用已加载')

应用注册

python
# settings.py
INSTALLED_APPS = [
    # 使用AppConfig类
    'blog.apps.BlogConfig',
    
    # 或简化形式
    'blog',
    
    # 第三方应用
    'rest_framework',
    'corsheaders',
    
    # Django内置应用
    'django.contrib.admin',
    'django.contrib.auth',
]

应用发现和加载

python
# Django应用加载过程
1. 读取INSTALLED_APPS设置
2. 导入每个应用的AppConfig
3. 调用AppConfig.ready()方法
4. 注册模型、管理命令等

# 检查已安装的应用
from django.apps import apps

# 获取所有应用
all_apps = apps.get_app_configs()
for app in all_apps:
    print(f"应用: {app.name}, 标签: {app.label}")

# 获取特定应用
blog_app = apps.get_app_config('blog')
print(f"应用名称: {blog_app.verbose_name}")

# 获取应用的模型
blog_models = blog_app.get_models()
for model in blog_models:
    print(f"模型: {model.__name__}")

中间件系统

中间件概念

中间件是Django请求/响应处理的钩子框架,它是一个轻量级的插件系统,用于全局改变Django的输入或输出。

python
# 中间件执行顺序
请求阶段(从上到下):
SecurityMiddleware
SessionMiddleware  
CommonMiddleware
CsrfViewMiddleware
AuthenticationMiddleware
MessageMiddleware
XFrameOptionsMiddleware

  视图处理

响应阶段(从下到上):
XFrameOptionsMiddleware
MessageMiddleware
AuthenticationMiddleware
CsrfViewMiddleware
CommonMiddleware
SessionMiddleware
SecurityMiddleware

内置中间件

python
# settings.py
MIDDLEWARE = [
    # 安全中间件 - 添加安全相关的HTTP头
    'django.middleware.security.SecurityMiddleware',
    
    # 会话中间件 - 启用会话支持
    'django.contrib.sessions.middleware.SessionMiddleware',
    
    # 通用中间件 - 处理URL重写、ETags等
    'django.middleware.common.CommonMiddleware',
    
    # CSRF保护中间件
    'django.middleware.csrf.CsrfViewMiddleware',
    
    # 认证中间件 - 添加user属性到request
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    
    # 消息中间件 - 启用消息框架
    'django.contrib.messages.middleware.MessageMiddleware',
    
    # 点击劫持保护中间件
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

自定义中间件

python
# middleware.py
import time
import logging
from django.utils.deprecation import MiddlewareMixin

class RequestLoggingMiddleware:
    """请求日志中间件"""
    
    def __init__(self, get_response):
        self.get_response = get_response
        self.logger = logging.getLogger(__name__)
    
    def __call__(self, request):
        # 请求处理前
        start_time = time.time()
        self.logger.info(f"请求开始: {request.method} {request.path}")
        
        # 调用下一个中间件或视图
        response = self.get_response(request)
        
        # 响应处理后
        duration = time.time() - start_time
        self.logger.info(f"请求完成: {response.status_code} ({duration:.2f}s)")
        
        return response
    
    def process_exception(self, request, exception):
        """处理异常"""
        self.logger.error(f"请求异常: {request.path} - {exception}")
        return None

class CustomHeaderMiddleware:
    """自定义HTTP头中间件"""
    
    def __init__(self, get_response):
        self.get_response = get_response
    
    def __call__(self, request):
        response = self.get_response(request)
        
        # 添加自定义头
        response['X-Custom-Header'] = 'MyValue'
        response['X-Request-ID'] = getattr(request, 'request_id', 'unknown')
        
        return response

# 基于类的中间件(旧式)
class LegacyMiddleware(MiddlewareMixin):
    def process_request(self, request):
        """处理请求"""
        request.custom_attribute = 'custom_value'
        return None
    
    def process_response(self, request, response):
        """处理响应"""
        response['X-Legacy-Header'] = 'legacy_value'
        return response

中间件配置和使用

python
# settings.py
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'myapp.middleware.RequestLoggingMiddleware',  # 自定义中间件
    'django.contrib.sessions.middleware.SessionMiddleware',
    'myapp.middleware.CustomHeaderMiddleware',    # 自定义中间件
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

# 条件性中间件
if DEBUG:
    MIDDLEWARE += ['debug_toolbar.middleware.DebugToolbarMiddleware']

信号系统

Django信号概念

Django信号是一种调度器,允许解耦的应用程序在框架的其他地方发生操作时得到通知。

python
# 常用的Django信号
from django.db.models.signals import (
    pre_save, post_save,           # 保存前后
    pre_delete, post_delete,       # 删除前后
    m2m_changed,                   # 多对多关系变化
)
from django.contrib.auth.signals import (
    user_logged_in,                # 用户登录
    user_logged_out,               # 用户登出
    user_login_failed,             # 登录失败
)
from django.core.signals import (
    request_started,               # 请求开始
    request_finished,              # 请求结束
)

信号处理器

python
# signals.py
from django.db.models.signals import post_save, pre_delete
from django.contrib.auth.signals import user_logged_in
from django.contrib.auth.models import User
from django.dispatch import receiver
from .models import Profile, Article

@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    """用户创建时自动创建用户资料"""
    if created:
        Profile.objects.create(user=instance)
        print(f"为用户 {instance.username} 创建了资料")

@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
    """用户保存时同时保存用户资料"""
    if hasattr(instance, 'profile'):
        instance.profile.save()

@receiver(user_logged_in)
def log_user_login(sender, request, user, **kwargs):
    """记录用户登录"""
    import logging
    logger = logging.getLogger(__name__)
    logger.info(f"用户 {user.username}{request.META.get('REMOTE_ADDR')} 登录")

@receiver(pre_delete, sender=Article)
def backup_article_before_delete(sender, instance, **kwargs):
    """删除文章前备份"""
    import json
    backup_data = {
        'title': instance.title,
        'content': instance.content,
        'created_at': instance.created_at.isoformat(),
    }
    
    # 保存到备份文件或数据库
    with open(f'backup_article_{instance.id}.json', 'w') as f:
        json.dump(backup_data, f)

# 手动连接信号(不使用装饰器)
def article_saved_handler(sender, instance, created, **kwargs):
    if created:
        print(f"新文章创建: {instance.title}")
    else:
        print(f"文章更新: {instance.title}")

post_save.connect(article_saved_handler, sender=Article)

自定义信号

python
# signals.py
import django.dispatch

# 定义自定义信号
article_published = django.dispatch.Signal()
user_profile_updated = django.dispatch.Signal()

# 在模型中发送信号
# models.py
from django.db import models
from .signals import article_published

class Article(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    is_published = models.BooleanField(default=False)
    
    def publish(self):
        self.is_published = True
        self.save()
        
        # 发送自定义信号
        article_published.send(
            sender=self.__class__,
            instance=self,
            user=self.author
        )

# 处理自定义信号
@receiver(article_published)
def notify_subscribers(sender, instance, user, **kwargs):
    """文章发布时通知订阅者"""
    print(f"文章 '{instance.title}' 已发布,作者: {user}")
    # 发送邮件通知、推送消息等

日志系统

日志配置

python
# settings.py
import os

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            'format': '{levelname} {asctime} {module} {process:d} {thread:d} {message}',
            'style': '{',
        },
        'simple': {
            'format': '{levelname} {message}',
            'style': '{',
        },
    },
    'filters': {
        'require_debug_true': {
            '()': 'django.utils.log.RequireDebugTrue',
        },
    },
    'handlers': {
        'console': {
            'level': 'INFO',
            'filters': ['require_debug_true'],
            'class': 'logging.StreamHandler',
            'formatter': 'simple'
        },
        'file': {
            'level': 'INFO',
            'class': 'logging.FileHandler',
            'filename': os.path.join(BASE_DIR, 'logs', 'django.log'),
            'formatter': 'verbose',
        },
        'mail_admins': {
            'level': 'ERROR',
            'class': 'django.utils.log.AdminEmailHandler',
            'formatter': 'verbose',
        }
    },
    'root': {
        'handlers': ['console'],
    },
    'loggers': {
        'django': {
            'handlers': ['console', 'file'],
            'level': 'INFO',
        },
        'django.request': {
            'handlers': ['mail_admins'],
            'level': 'ERROR',
            'propagate': True,
        },
        'myapp': {
            'handlers': ['console', 'file'],
            'level': 'DEBUG',
            'propagate': True,
        },
    }
}

使用日志

python
# views.py
import logging

# 获取日志记录器
logger = logging.getLogger(__name__)

def my_view(request):
    logger.debug('这是调试信息')
    logger.info('这是信息日志')
    logger.warning('这是警告信息')
    logger.error('这是错误信息')
    logger.critical('这是严重错误')
    
    try:
        # 一些可能出错的代码
        result = risky_operation()
    except Exception as e:
        logger.exception('操作失败: %s', e)
        raise
    
    return render(request, 'template.html')

# 使用结构化日志
logger.info('用户登录', extra={
    'user_id': request.user.id,
    'ip_address': request.META.get('REMOTE_ADDR'),
    'user_agent': request.META.get('HTTP_USER_AGENT'),
})

缓存系统

缓存配置

python
# settings.py

# 内存缓存(开发环境)
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
        'LOCATION': 'unique-snowflake',
    }
}

# Redis缓存(推荐生产环境)
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.redis.RedisCache',
        'LOCATION': 'redis://127.0.0.1:6379/1',
        'OPTIONS': {
            'CLIENT_CLASS': 'django_redis.client.DefaultClient',
        }
    }
}

# Memcached缓存
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.PyMemcacheCache',
        'LOCATION': '127.0.0.1:11211',
    }
}

# 多级缓存
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.redis.RedisCache',
        'LOCATION': 'redis://127.0.0.1:6379/1',
    },
    'sessions': {
        'BACKEND': 'django.core.cache.backends.redis.RedisCache',
        'LOCATION': 'redis://127.0.0.1:6379/2',
    }
}

# 会话缓存
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
SESSION_CACHE_ALIAS = 'sessions'

使用缓存

python
# views.py
from django.core.cache import cache
from django.views.decorators.cache import cache_page
from django.utils.decorators import method_decorator

# 手动缓存
def expensive_view(request):
    # 尝试从缓存获取
    result = cache.get('expensive_calculation')
    
    if result is None:
        # 缓存未命中,执行计算
        result = perform_expensive_calculation()
        
        # 存储到缓存,过期时间300秒
        cache.set('expensive_calculation', result, 300)
    
    return render(request, 'result.html', {'result': result})

# 视图缓存装饰器
@cache_page(60 * 15)  # 缓存15分钟
def cached_view(request):
    return render(request, 'template.html')

# 类视图缓存
@method_decorator(cache_page(60 * 15), name='dispatch')
class CachedView(View):
    def get(self, request):
        return render(request, 'template.html')

# 模板片段缓存
# template.html
{% load cache %}
{% cache 500 sidebar request.user.username %}
    <!-- 复杂的侧边栏内容 -->
{% endcache %}

# 低级缓存API
from django.core.cache import caches

# 使用特定缓存
cache = caches['sessions']
cache.set('key', 'value', 300)
value = cache.get('key')

# 批量操作
cache.set_many({'a': 1, 'b': 2, 'c': 3}, 300)
values = cache.get_many(['a', 'b', 'c'])

# 原子操作
cache.add('key', 'value', 300)  # 只在键不存在时设置
cache.delete('key')
cache.clear()  # 清空所有缓存

本章小结

本章深入介绍了Django的基础概念和核心系统:

关键要点:

  • MVT架构:Model-View-Template设计模式
  • 设置系统:项目配置和环境管理
  • 应用配置:AppConfig类和应用生命周期
  • 中间件系统:请求/响应处理钩子
  • 信号系统:解耦的事件通知机制
  • 日志系统:结构化日志记录
  • 缓存系统:性能优化工具

重要概念:

  • Django的请求-响应流程
  • 中间件的执行顺序和作用
  • 信号的发送和接收机制
  • 缓存策略和使用场景

最佳实践:

  • 合理组织设置文件
  • 正确使用中间件顺序
  • 适当使用信号处理业务逻辑
  • 配置结构化日志记录
  • 选择合适的缓存策略

在下一章中,我们将学习Django的视图和URL配置,了解如何处理HTTP请求和响应。

延伸阅读

本站内容仅供学习和研究使用。