数据库完整指南:从基础到 Django 集成

目录

  1. 数据库基础概念

  2. 关系型数据库

  3. Django 数据库配置

  4. Django 模型详解

  5. 数据库迁移

  6. 数据库查询

  7. 数据库关系

  8. 数据库优化

  9. 生产环境部署

数据库基础概念

什么是数据库?

数据库是结构化信息的集合,用于高效存储、管理和检索数据。

数据库类型

  • 关系型数据库:MySQL、PostgreSQL、SQLite

  • 非关系型数据库:MongoDB、Redis

  • 时序数据库:InfluxDB

  • 图数据库:Neo4j

ACID 原则

  • 原子性:事务要么全部完成,要么全部不完成

  • 一致性:事务必须使数据库从一种一致状态变为另一种一致状态

  • 隔离性:并发事务之间互不干扰

  • 持久性:事务完成后,对数据库的修改是永久的

关系型数据库

核心概念

sql

复制代码
-- 数据库操作
CREATE DATABASE mydb;
USE mydb;

-- 表操作
CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50) UNIQUE NOT NULL,
    email VARCHAR(100) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 数据操作
INSERT INTO users (username, email) VALUES ('john', 'john@example.com');
SELECT * FROM users WHERE username = 'john';
UPDATE users SET email = 'new@example.com' WHERE id = 1;
DELETE FROM users WHERE id = 1;

常见关系型数据库比较

数据库 特点 适用场景
MySQL 流行、成熟、社区强大 Web应用、中小型系统
PostgreSQL 功能丰富、标准兼容性好 复杂应用、地理数据
SQLite 轻量级、零配置 移动应用、小型项目
Oracle 企业级、功能强大 大型企业系统

Django 数据库配置

基本配置

python

复制代码
# settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}

PostgreSQL 配置

python

复制代码
# settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'mydatabase',
        'USER': 'mydatabaseuser',
        'PASSWORD': 'mypassword',
        'HOST': 'localhost',
        'PORT': '5432',
        'CONN_MAX_AGE': 600,  # 连接存活时间(秒)
        'OPTIONS': {
            'connect_timeout': 10,
        }
    }
}

MySQL 配置

python

复制代码
# settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'mydatabase',
        'USER': 'mydatabaseuser',
        'PASSWORD': 'mypassword',
        'HOST': 'localhost',
        'PORT': '3306',
        'OPTIONS': {
            'charset': 'utf8mb4',
            'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
        },
        'TEST': {
            'CHARSET': 'utf8mb4',
            'COLLATION': 'utf8mb4_unicode_ci',
        }
    }
}

多数据库配置

python

复制代码
# settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'primary_db',
        # ... 其他配置
    },
    'read_replica': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'replica_db',
        # ... 其他配置
    },
    'logging': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'logs.db',
    }
}

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

Django 模型详解

基础模型定义

python

复制代码
# models.py
from django.db import models
from django.urls import reverse
from django.core.validators import MinLengthValidator, MaxValueValidator

class TimestampModel(models.Model):
    """抽象基类,提供时间戳字段"""
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    class Meta:
        abstract = True

class User(TimestampModel):
    # 字段类型
    username = models.CharField(
        max_length=50,
        unique=True,
        validators=[MinLengthValidator(3)],
        verbose_name='用户名'
    )
    email = models.EmailField(unique=True, verbose_name='邮箱')
    age = models.PositiveIntegerField(
        null=True,
        blank=True,
        validators=[MaxValueValidator(150)],
        verbose_name='年龄'
    )
    is_active = models.BooleanField(default=True, verbose_name='是否激活')
    birth_date = models.DateField(null=True, blank=True, verbose_name='出生日期')
    salary = models.DecimalField(
        max_digits=10,
        decimal_places=2,
        null=True,
        blank=True,
        verbose_name='薪资'
    )
    bio = models.TextField(blank=True, verbose_name='个人简介')
    avatar = models.ImageField(
        upload_to='avatars/',
        null=True,
        blank=True,
        verbose_name='头像'
    )
    
    # 元数据
    class Meta:
        verbose_name = '用户'
        verbose_name_plural = '用户'
        ordering = ['-created_at']
        indexes = [
            models.Index(fields=['username']),
            models.Index(fields=['email', 'is_active']),
        ]
        constraints = [
            models.CheckConstraint(
                check=models.Q(age__gte=0),
                name='age_positive'
            )
        ]
    
    def __str__(self):
        return self.username
    
    def get_absolute_url(self):
        return reverse('user_detail', kwargs={'pk': self.pk})
    
    @property
    def display_name(self):
        return f"{self.username} ({self.email})"
    
    def save(self, *args, **kwargs):
        # 保存前的自定义逻辑
        self.email = self.email.lower()
        super().save(*args, **kwargs)

字段类型详解

字段类型 说明 对应数据库类型
CharField 字符串字段 VARCHAR
TextField 大文本字段 TEXT
IntegerField 整数字段 INTEGER
DecimalField 十进制数字段 NUMERIC
BooleanField 布尔字段 BOOLEAN
DateTimeField 日期时间字段 DATETIME
DateField 日期字段 DATE
TimeField 时间字段 TIME
EmailField 邮箱字段 VARCHAR
URLField URL字段 VARCHAR
FileField 文件字段 VARCHAR
ImageField 图片字段 VARCHAR

字段选项

python

复制代码
class ExampleModel(models.Model):
    # 常用字段选项
    name = models.CharField(
        max_length=100,
        null=True,           # 数据库允许NULL
        blank=True,          # 表单验证允许空值
        default='Unknown',   # 默认值
        unique=True,         # 唯一值
        db_index=True,       # 创建索引
        choices=[            # 选择项
            ('draft', '草稿'),
            ('published', '已发布'),
        ],
        help_text='请输入名称',  # 帮助文本
        verbose_name='名称'     # 可读名称
    )

数据库迁移

迁移命令

bash

复制代码
# 创建迁移文件
python manage.py makemigrations

# 查看迁移SQL
python manage.py sqlmigrate myapp 0001

# 应用迁移
python manage.py migrate

# 查看迁移状态
python manage.py showmigrations

# 撤销迁移
python manage.py migrate myapp 0001

# 数据迁移
python manage.py makemigrations --empty myapp

自定义迁移

python

复制代码
# myapp/migrations/0002_custom_migration.py
from django.db import migrations, models

def add_default_categories(apps, schema_editor):
    Category = apps.get_model('myapp', 'Category')
    Category.objects.bulk_create([
        Category(name='技术'),
        Category(name='生活'),
        Category(name='旅游'),
    ])

def remove_default_categories(apps, schema_editor):
    Category = apps.get_model('myapp', 'Category')
    Category.objects.filter(name__in=['技术', '生活', '旅游']).delete()

class Migration(migrations.Migration):
    dependencies = [
        ('myapp', '0001_initial'),
    ]
    
    operations = [
        migrations.RunPython(
            add_default_categories,
            remove_default_categories
        ),
    ]

数据库查询

基础查询

python

复制代码
from myapp.models import User, Post
from django.db.models import Q, Count, Avg, Sum

# 创建
user = User.objects.create(username='john', email='john@example.com')

# 查询所有
users = User.objects.all()

# 过滤查询
active_users = User.objects.filter(is_active=True)
john_users = User.objects.filter(username__contains='john')
recent_users = User.objects.filter(created_at__gte='2024-01-01')

# 排除查询
inactive_users = User.objects.exclude(is_active=True)

# 获取单个对象
try:
    user = User.objects.get(id=1)
except User.DoesNotExist:
    user = None

# 快捷方法
user = User.objects.filter(id=1).first()

# 复杂查询
complex_query = User.objects.filter(
    Q(is_active=True) & 
    (Q(username__startswith='j') | Q(email__contains='example'))
)

# 排序
users_ordered = User.objects.order_by('-created_at', 'username')

# 切片
recent_10_users = User.objects.order_by('-created_at')[:10]

高级查询方法

python

复制代码
# 聚合查询
from django.db.models import Count, Avg, Max, Min

stats = User.objects.aggregate(
    total_users=Count('id'),
    avg_age=Avg('age'),
    max_salary=Max('salary')
)

# 分组查询
user_posts_count = User.objects.annotate(
    post_count=Count('posts')
).filter(post_count__gt=0)

# 值列表
usernames = User.objects.values_list('username', flat=True)
user_data = User.objects.values('username', 'email')

# 选择相关对象(减少查询)
users_with_posts = User.objects.select_related('profile').prefetch_related('posts')

# 原生SQL查询
from django.db import connection

with connection.cursor() as cursor:
    cursor.execute("SELECT * FROM myapp_user WHERE age > %s", [18])
    rows = cursor.fetchall()

# 使用raw方法
users = User.objects.raw('SELECT * FROM myapp_user WHERE is_active = %s', [True])

查询性能优化

python

复制代码
# 不好的查询 - N+1 问题
users = User.objects.all()
for user in users:
    print(user.profile.bio)  # 每次循环都会查询数据库

# 好的查询 - 使用select_related
users = User.objects.select_related('profile').all()
for user in users:
    print(user.profile.bio)  # 一次性查询

# 使用prefetch_related处理多对多关系
posts = Post.objects.prefetch_related('tags').all()
for post in posts:
    print(post.tags.all())  # 一次性预加载

数据库关系

一对一关系

python

复制代码
class UserProfile(models.Model):
    user = models.OneToOneField(
        User,
        on_delete=models.CASCADE,
        related_name='profile'
    )
    bio = models.TextField(blank=True)
    location = models.CharField(max_length=100, blank=True)
    
    def __str__(self):
        return f"{self.user.username}的档案"

# 使用示例
user = User.objects.get(id=1)
profile = user.profile  # 通过related_name访问

一对多关系

python

复制代码
class Post(TimestampModel):
    author = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name='posts'
    )
    title = models.CharField(max_length=200)
    content = models.TextField()
    is_published = models.BooleanField(default=False)
    
    class Meta:
        ordering = ['-created_at']
    
    def __str__(self):
        return self.title

# 使用示例
user = User.objects.get(id=1)
user_posts = user.posts.all()  # 用户的所有文章
latest_post = user.posts.first()

多对多关系

python

复制代码
class Tag(models.Model):
    name = models.CharField(max_length=50, unique=True)
    created_at = models.DateTimeField(auto_now_add=True)
    
    def __str__(self):
        return self.name

class Post(TimestampModel):
    # ... 其他字段
    tags = models.ManyToManyField(
        Tag,
        related_name='posts',
        blank=True
    )
    
    def get_tag_names(self):
        return list(self.tags.values_list('name', flat=True))

# 使用示例
post = Post.objects.get(id=1)
post.tags.add(tag1, tag2)  # 添加标签
post.tags.remove(tag1)     # 移除标签
post.tags.clear()          # 清空所有标签

自定义中间表

python

复制代码
class PostTag(models.Model):
    post = models.ForeignKey(Post, on_delete=models.CASCADE)
    tag = models.ForeignKey(Tag, on_delete=models.CASCADE)
    added_by = models.ForeignKey(User, on_delete=models.CASCADE)
    added_at = models.DateTimeField(auto_now_add=True)
    
    class Meta:
        unique_together = ['post', 'tag']

class Post(models.Model):
    tags = models.ManyToManyField(
        Tag,
        through='PostTag',
        related_name='posts'
    )

数据库优化

索引优化

python

复制代码
class User(models.Model):
    username = models.CharField(max_length=50, db_index=True)
    email = models.EmailField(unique=True)
    
    class Meta:
        indexes = [
            models.Index(fields=['username', 'email']),
            models.Index(fields=['-created_at']),
        ]

查询优化技巧

python

复制代码
# 1. 使用only和defer选择特定字段
users = User.objects.only('username', 'email')  # 只查询指定字段
users = User.objects.defer('bio')  # 排除指定字段

# 2. 使用exists检查存在性
if User.objects.filter(username='john').exists():
    # 处理逻辑

# 3. 使用count获取数量
user_count = User.objects.count()

# 4. 使用bulk操作
users = [User(username=f'user{i}') for i in range(1000)]
User.objects.bulk_create(users)  # 批量创建

# 5. 使用update批量更新
User.objects.filter(is_active=False).update(is_active=True)

数据库连接池

python

复制代码
# 使用django-db-connection-pool
DATABASES = {
    'default': {
        'ENGINE': 'dj_db_conn_pool.backends.mysql',
        'NAME': 'mydatabase',
        'POOL_OPTIONS': {
            'POOL_SIZE': 10,
            'MAX_OVERFLOW': 20,
            'RECYCLE': 3600,
        }
    }
}

生产环境部署

数据库备份

python

复制代码
# management/commands/backup_database.py
from django.core.management.base import BaseCommand
from django.conf import settings
import subprocess
import os
from datetime import datetime

class Command(BaseCommand):
    help = '备份数据库'
    
    def handle(self, *args, **options):
        timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
        backup_file = f'backup_{timestamp}.sql'
        
        if settings.DATABASES['default']['ENGINE'] == 'django.db.backends.postgresql':
            cmd = [
                'pg_dump',
                '-h', settings.DATABASES['default']['HOST'],
                '-U', settings.DATABASES['default']['USER'],
                '-d', settings.DATABASES['default']['NAME'],
                '-f', backup_file
            ]
            env = os.environ.copy()
            env['PGPASSWORD'] = settings.DATABASES['default']['PASSWORD']
            subprocess.run(cmd, env=env)
        
        self.stdout.write(
            self.style.SUCCESS(f'备份完成: {backup_file}')
        )

数据库监控

python

复制代码
# 使用Django Debug Toolbar
INSTALLED_APPS = [
    # ...
    'debug_toolbar',
]

MIDDLEWARE = [
    'debug_toolbar.middleware.DebugToolbarMiddleware',
    # ...
]

# 数据库查询日志
LOGGING = {
    'version': 1,
    'handlers': {
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'level': 'DEBUG',
            'handlers': ['console'],
        }
    }
}

生产环境配置

python

复制代码
# settings/production.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': os.getenv('DB_NAME'),
        'USER': os.getenv('DB_USER'),
        'PASSWORD': os.getenv('DB_PASSWORD'),
        'HOST': os.getenv('DB_HOST'),
        'PORT': os.getenv('DB_PORT', '5432'),
        'CONN_MAX_AGE': 600,
        'OPTIONS': {
            'sslmode': 'require',
        }
    }
}

# 数据库性能配置
DATABASES['default']['ATOMIC_REQUESTS'] = False  # 提高性能
DATABASES['default']['AUTOCOMMIT'] = True

数据库健康检查

python

复制代码
# health_checks.py
from django.db import connection
from django.http import JsonResponse

def database_health_check(request):
    try:
        with connection.cursor() as cursor:
            cursor.execute("SELECT 1")
            result = cursor.fetchone()
        
        if result[0] == 1:
            return JsonResponse({'status': 'healthy'})
        else:
            return JsonResponse({'status': 'unhealthy'}, status=500)
    
    except Exception as e:
        return JsonResponse({'status': 'error', 'message': str(e)}, status=500)

总结

数据库是Web应用的核心组件,正确的数据库设计和优化对应用性能至关重要。Django提供了强大的ORM系统,使得数据库操作更加简单和安全。通过合理的模型设计、查询优化和适当的数据库配置,可以构建出高性能、可扩展的Web应用。

记住以下最佳实践:

  1. 合理设计数据库关系

  2. 为常用查询字段添加索引

  3. 使用select_related和prefetch_related优化查询

  4. 定期备份数据库

  5. 在生产环境使用连接池

  6. 监控数据库性能

  7. 使用迁移管理数据库结构变更

通过掌握这些数据库知识,您将能够构建出更加健壮和高效的Django应用。

相关推荐
Allen_LVyingbo3 小时前
医疗科研管理系统到院级生命科学平台的升级路径
python·信息可视化·健康医疗·ai编程
程序新视界3 小时前
MySQL的OR条件查询不走索引及解决方案
数据库·后端·mysql
2301_772093563 小时前
tuchuang_myfiles&&share文件列表_共享文件
大数据·前端·javascript·数据库·redis·分布式·缓存
点灯小铭3 小时前
基于单片机的罐体压力控制器设计与实现
数据库·单片机·mongodb·毕业设计·课程设计
MoRanzhi12033 小时前
11. Pandas 数据分类与区间分组(cut 与 qcut)
人工智能·python·机器学习·数学建模·分类·数据挖掘·pandas
Pr Young3 小时前
MVCC 多版本并发控制
数据库·后端·mysql
码界筑梦坊4 小时前
276-基于Python的爱奇艺视频数据可视化分析系统
开发语言·python·信息可视化
云博客-资源宝4 小时前
【防火墙源码】WordPress防火墙插件1.0测试版
linux·服务器·数据库
我的xiaodoujiao5 小时前
从 0 到 1 搭建 Python 语言 Web UI自动化测试学习系列 9--基础知识 5--常用函数 3
前端·python·测试工具·ui