1. Django框架概述:Python Web开发的瑞士军刀
Django作为Python生态中最负盛名的全栈Web框架,自2005年诞生以来就以其"开箱即用"的特性闻名。这个采用MTV架构模式的框架,本质上是一个高效的工具集合,包含:
- 对象关系映射器(ORM):用Python类定义数据模型,自动生成数据库表结构
- 模板引擎:分离业务逻辑与展示层,支持模板继承机制
- 表单处理:内置CSRF防护、数据验证和清理功能
- 管理后台:自动生成的内容管理系统,节省80%的CRUD开发时间
- 路由系统:URLconf配置将URL模式映射到视图函数
- 认证系统:用户、组、权限管理一应俱全
实战经验:在中小型项目中使用Django Admin可以直接获得生产可用的后台,这是其他框架难以比拟的优势。我曾用3天时间基于Admin定制出一个出版社图书管理系统,而传统开发至少需要2周。
2. 环境搭建与项目初始化
2.1 开发环境配置
推荐使用Python 3.8+版本,通过venv创建隔离环境:
python -m venv django_env source django_env/bin/activate # Linux/Mac django_env\Scripts\activate.bat # Windows pip install django==4.22.2 项目脚手架生成
执行以下命令创建项目骨架:
django-admin startproject myproject cd myproject python manage.py startapp myapp关键目录结构解析:
myproject/ ├── manage.py # 项目管理脚本 ├── myproject/ # 全局配置目录 │ ├── __init__.py │ ├── settings.py # 数据库/中间件/模板等配置 │ ├── urls.py # 主路由配置 │ └── wsgi.py # WSGI入口 └── myapp/ # 应用目录 ├── migrations/ # 数据库迁移文件 ├── admin.py # Admin配置 ├── models.py # 数据模型 ├── views.py # 业务逻辑 └── templates/ # 模板文件2.3 基础配置要点
在settings.py中必须关注的配置项:
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'myapp', # 新增应用 ] DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': BASE_DIR / 'db.sqlite3', } } STATIC_URL = '/static/' # 静态文件URL前缀 STATICFILES_DIRS = [BASE_DIR / "static"] # 静态文件目录3. 核心组件深度解析
3.1 模型层(Model)设计
模型定义示例(myapp/models.py):
from django.db import models from django.core.validators import MinLengthValidator class Author(models.Model): name = models.CharField(max_length=100) email = models.EmailField(unique=True) bio = models.TextField( validators=[MinLengthValidator(10)], help_text="至少10个字符的作者简介" ) def __str__(self): return self.name class Book(models.Model): title = models.CharField(max_length=200) author = models.ForeignKey(Author, on_delete=models.CASCADE) publish_date = models.DateField() price = models.DecimalField(max_digits=6, decimal_places=2) stock = models.PositiveIntegerField(default=0) class Meta: ordering = ['-publish_date'] indexes = [ models.Index(fields=['title']), ]生成迁移并同步数据库:
python manage.py makemigrations python manage.py migrate3.2 视图层(View)开发
函数视图与类视图对比示例:
# 函数视图 from django.shortcuts import render, get_object_or_404 from .models import Book def book_list(request): books = Book.objects.filter(stock__gt=0) return render(request, 'book/list.html', {'books': books}) # 类视图 from django.views.generic import ListView, DetailView class BookListView(ListView): model = Book template_name = 'book/list.html' context_object_name = 'books' paginate_by = 10 def get_queryset(self): return Book.objects.filter(stock__gt=0) class BookDetailView(DetailView): model = Book template_name = 'book/detail.html'3.3 模板系统实战
模板继承示例(templates/base.html):
<!DOCTYPE html> <html> <head> <title>{% block title %}默认标题{% endblock %}</title> {% block css %}{% endblock %} </head> <body> <nav>导航栏内容</nav> <main> {% block content %}{% endblock %} </main> <footer>页脚信息</footer> {% block js %}{% endblock %} </body> </html>子模板示例(templates/book/list.html):
{% extends "base.html" %} {% block title %}图书列表{% endblock %} {% block content %} <ul> {% for book in books %} <li> <a href="{{ book.get_absolute_url }}">{{ book.title }}</a> - {{ book.author.name }} </li> {% empty %} <li>暂无库存图书</li> {% endfor %} </ul> {% endblock %}4. Django Admin深度定制
4.1 基础配置
在myapp/admin.py中注册模型:
from django.contrib import admin from .models import Author, Book @admin.register(Book) class BookAdmin(admin.ModelAdmin): list_display = ('title', 'author', 'price', 'stock') list_filter = ('author', 'publish_date') search_fields = ('title', 'author__name') raw_id_fields = ('author',) date_hierarchy = 'publish_date' ordering = ('-publish_date',) admin.site.register(Author)4.2 高级定制技巧
- 自定义表单验证:
class BookAdminForm(forms.ModelForm): class Meta: model = Book fields = '__all__' def clean_price(self): price = self.cleaned_data['price'] if price < 0: raise forms.ValidationError("价格不能为负数") return price class BookAdmin(admin.ModelAdmin): form = BookAdminForm- 添加自定义操作:
def make_available(modeladmin, request, queryset): queryset.update(stock=100) make_available.short_description = "补货100本" class BookAdmin(admin.ModelAdmin): actions = [make_available]5. 实战:构建RESTful API
5.1 DRF基础配置
安装DRF并创建序列化器:
pip install djangorestframework在settings.py中添加:
INSTALLED_APPS += ['rest_framework']创建序列化器(myapp/serializers.py):
from rest_framework import serializers from .models import Book class BookSerializer(serializers.ModelSerializer): author_name = serializers.CharField(source='author.name', read_only=True) class Meta: model = Book fields = ['id', 'title', 'author', 'author_name', 'price', 'stock']5.2 视图集配置
from rest_framework import viewsets from .models import Book from .serializers import BookSerializer class BookViewSet(viewsets.ModelViewSet): queryset = Book.objects.all() serializer_class = BookSerializer filterset_fields = ['author', 'stock'] search_fields = ['title', 'author__name'] ordering_fields = ['price', 'publish_date']5.3 路由配置
from django.urls import path, include from rest_framework.routers import DefaultRouter from myapp import views router = DefaultRouter() router.register(r'books', views.BookViewSet) urlpatterns = [ path('api/', include(router.urls)), path('api-auth/', include('rest_framework.urls')), ]6. 部署上线关键步骤
6.1 生产环境配置
修改settings.py:
DEBUG = False ALLOWED_HOSTS = ['yourdomain.com', 'localhost'] STATIC_ROOT = BASE_DIR / 'staticfiles'安装必要依赖:
pip install gunicorn psycopg2-binary6.2 Nginx配置示例
server { listen 80; server_name yourdomain.com; location /static/ { alias /path/to/staticfiles; } location / { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }6.3 启动服务
使用Gunicorn启动:
gunicorn --workers 3 --bind 127.0.0.1:8000 myproject.wsgi:application7. 性能优化实战技巧
- 查询优化:
# 反例:N+1查询问题 books = Book.objects.all() for book in books: print(book.author.name) # 每次循环都查询数据库 # 正例:使用select_related books = Book.objects.select_related('author').all()- 缓存策略:
from django.core.cache import cache def get_books(): books = cache.get('all_books') if not books: books = list(Book.objects.all()) cache.set('all_books', books, timeout=3600) return books- 异步任务: 安装Celery:
pip install celery redis创建任务(myapp/tasks.py):
from celery import shared_task from django.core.mail import send_mail @shared_task def send_notification_email(subject, message, recipient): send_mail( subject, message, 'admin@example.com', [recipient], fail_silently=False, )8. 安全防护最佳实践
- CSRF防护:
<form method="post"> {% csrf_token %} <!-- 表单内容 --> </form>- XSS防护:
from django.utils.html import escape def user_profile(request): user_input = request.GET.get('q', '') # 自动转义HTML return render(request, 'profile.html', {'data': escape(user_input)})- SQL注入防护:
# Django ORM自动防护 Book.objects.filter(title__contains=request.GET.get('query')) # 原始SQL必须使用参数化 from django.db import connection with connection.cursor() as cursor: cursor.execute("SELECT * FROM myapp_book WHERE title = %s", [user_input])9. 测试驱动开发
9.1 单元测试示例
from django.test import TestCase from django.urls import reverse from .models import Author class AuthorTests(TestCase): @classmethod def setUpTestData(cls): Author.objects.create(name='Test Author', email='author@example.com') def test_author_listing(self): author = Author.objects.get(id=1) self.assertEqual(author.name, 'Test Author') self.assertEqual(author.email, 'author@example.com') def test_author_list_view(self): response = self.client.get(reverse('author-list')) self.assertEqual(response.status_code, 200) self.assertContains(response, 'Test Author') self.assertTemplateUsed(response, 'author/list.html')9.2 API测试
from rest_framework.test import APITestCase from rest_framework import status class BookAPITests(APITestCase): def test_create_book(self): author = Author.objects.create(name='API Author') data = { 'title': 'Django Book', 'author': author.id, 'price': '99.99', 'stock': 10 } response = self.client.post('/api/books/', data) self.assertEqual(response.status_code, status.HTTP_201_CREATED) self.assertEqual(response.data['title'], 'Django Book')10. 常见问题解决方案
- 静态文件404问题:
- 确保DEBUG=False时运行了collectstatic
- 检查Nginx/Apache配置的静态文件路径
- 验证STATIC_ROOT和STATIC_URL设置
- 数据库连接问题:
# PostgreSQL配置示例 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': 'mydatabase', 'USER': 'mydatabaseuser', 'PASSWORD': 'mypassword', 'HOST': '127.0.0.1', 'PORT': '5432', } }- 时区设置:
TIME_ZONE = 'Asia/Shanghai' USE_TZ = True # 建议启用时区支持- 性能分析工具:
pip install django-debug-toolbar配置settings.py:
INSTALLED_APPS += ['debug_toolbar'] MIDDLEWARE += ['debug_toolbar.middleware.DebugToolbarMiddleware'] INTERNAL_IPS = ['127.0.0.1']在开发过程中,我特别推荐使用django-extensions和ipython组合:
pip install django-extensions ipython python manage.py shell_plus --ipython这个增强的shell会自动导入所有模型,极大提升开发效率。对于复杂查询调试,可以使用:
from django.db import connection print(connection.queries) # 查看已执行的SQL语句