恐怖解谜密室逃脱
109.73M · 2026-03-09
遵循「电池已内置」(Batteries Included)理念 , 内置 ORM、Admin 后台、用户认证、表单验证等全套功能 , 适合快速开发从个人项目到企业级应用的各类 Web 系统。
本教程从环境搭建到完整项目实战,带你零基础掌握 Django 核心用法。
打开终端/命令提示符,执行以下命令安装最新稳定版 Django:
# 安装最新版
pip install django
# 验证安装(查看版本,当前稳定版为 5.0+)
django-admin --version
在开始写代码前,先理解 Django 的核心设计理念和架构:
Django 采用 MTV 模式(对应传统 MVC 架构),职责划分清晰:
| 组件 | 全称 | 作用 | 对应 MVC 中的角色 |
|---|---|---|---|
| Model(模型) | 数据模型 | 定义数据结构,操作数据库(增删改查) | Model |
| Template(模板) | 模板文件 | 定义页面展示样式(HTML+模板语法) | View |
| View(视图) | 视图函数/类 | 处理业务逻辑,连接 Model 和 Template | Controller |
执行以下命令创建名为 myfirstsite 的 Django 项目:
django-admin startproject myfirstsite
执行后会生成如下目录结构:
myfirstsite/ # 项目根目录
├── manage.py # 项目管理脚本(启动服务、创建App、数据库迁移等)
└── myfirstsite/ # 项目核心配置目录
├── __init__.py
├── asgi.py # ASGI 配置,适配异步 Web 服务器
├── settings.py # 全局配置文件(数据库、静态文件、应用注册等)
├── urls.py # 路由总入口
└── wsgi.py # WSGI 配置,适配传统 Web 服务器
进入项目根目录,创建名为 blog 的应用(后续以博客功能为例):
cd myfirstsite
python manage.py startapp blog
生成的 blog 目录结构:
blog/
├── __init__.py
├── admin.py # 配置 Admin 后台
├── apps.py # 应用配置
├── migrations/ # 数据库迁移文件(自动生成)
├── models.py # 数据模型
├── tests.py # 单元测试
└── views.py # 视图函数
打开 myfirstsite/settings.py,在 INSTALLED_APPS 中添加 blog 应用(Django 仅加载注册的应用):
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog', # 新增:注册 blog 应用
]
执行以下命令启动 Django 内置的开发服务器:
python manage.py runserver
终端输出如下信息表示启动成功:
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
Django version 5.0, using settings 'myfirstsite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
打开浏览器访问 ,看到 Django 默认欢迎页面,说明环境搭建成功。
打开 blog/models.py,定义博客文章(Article)模型,对应数据库中的 blog_article 表:
from django.db import models
from django.contrib.auth.models import User # 内置用户模型
# 博客文章模型
class Article(models.Model):
# 标题:字符串类型,最大长度 200,不允许为空
title = models.CharField(max_length=200, verbose_name="文章标题")
# 内容:文本类型,可存储大段文字
content = models.TextField(verbose_name="文章内容")
# 发布时间:自动设置为创建时间,无需手动赋值
pub_time = models.DateTimeField(auto_now_add=True, verbose_name="发布时间")
# 作者:关联内置 User 模型,一篇文章属于一个用户,用户删除则文章也删除(on_delete=models.CASCADE)
author = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="作者")
# 自定义显示名称(Admin 后台和终端中更易识别)
def __str__(self):
return self.title
# 元数据:设置模型的额外属性
class Meta:
verbose_name = "文章"
verbose_name_plural = "文章" # 复数形式(避免 Admin 显示为“Articles”)
ordering = ["-pub_time"] # 按发布时间倒序排列(最新的在前)
Django 通过「迁移文件」管理数据库结构,执行以下命令将模型同步到数据库:
# 生成迁移文件(记录模型的变化)
python manage.py makemigrations
# 执行迁移(将模型创建为数据库表)
python manage.py migrate
Django 内置的 Admin 后台可快速管理数据库数据,无需手动写增删改查页面。
打开 blog/admin.py,注册 Article 模型:
from django.contrib import admin
from .models import Article
# 注册 Article 模型
admin.site.register(Article)
执行以下命令,按提示输入用户名、邮箱、密码:
python manage.py createsuperuser
示例:
Username (leave blank to use 'yourname'): admin
Email address: admin@example.com
Password: 输入强密码(如 Admin123!)
Password (again): 重复密码
Superuser created successfully.
重启开发服务器,访问 ,输入超级用户账号密码登录。
登录后可看到「Articles」选项,点击即可添加、编辑、删除博客文章——这就是 Django 「电池已内置」的体现,几行代码实现完整的后台管理功能。
视图函数负责处理业务逻辑,接收请求并返回响应。
打开 blog/views.py,编写视图函数:
from django.shortcuts import render
from .models import Article
# 展示所有文章列表
def article_list(request):
# 从数据库查询所有文章(按发布时间倒序)
articles = Article.objects.all()
# 将文章数据传递给模板
return render(request, 'blog/article_list.html', {'articles': articles})
# 展示单篇文章详情
def article_detail(request, article_id):
# 根据 ID 查询单篇文章,若不存在则返回 404
article = Article.objects.get(id=article_id)
return render(request, 'blog/article_detail.html', {'article': article})
路由负责映射 URL 到视图函数,分为「项目总路由」和「应用子路由」(推荐解耦)。
在 blog 目录下创建 urls.py 文件,编写应用内路由:
from django.urls import path
from . import views
urlpatterns = [
# 文章列表页:
path('', views.article_list, name='article_list'),
# 文章详情页:(1 为文章 ID)
path('<int:article_id>/', views.article_detail, name='article_detail'),
]
打开 myfirstsite/urls.py,将应用路由挂载到总路由:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls), # Admin 后台路由
path('blog/', include('blog.urls')), # 挂载 blog 应用路由
]
模板负责页面展示,使用 Django 模板语法将视图传递的数据渲染为 HTML。
按以下结构创建模板目录(Django 默认读取 templates 目录下的模板):
myfirstsite/
├── blog/
│ └── templates/ # 应用级模板目录(推荐)
│ └── blog/
│ ├── article_list.html # 文章列表模板
│ └── article_detail.html # 文章详情模板
└── manage.py
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>我的博客</title>
<style>
.article { margin: 20px 0; padding: 10px; border-bottom: 1px solid #eee; }
.title { font-size: 18px; color: #2c3e50; }
.pub-time { color: #999; font-size: 12px; }
</style>
</head>
<body>
<h1>我的博客</h1>
{% if articles %}
{% for article in articles %}
<div class="article">
<h2 class="title">
<a href="{% url 'article_detail' article.id %}">{{ article.title }}</a>
</h2>
<p class="pub-time">发布时间:{{ article.pub_time|date:"Y-m-d H:i" }}</p>
<p>作者:{{ article.author.username }}</p>
<p>{{ article.content|truncatechars:200 }}</p> <!-- 截取前200个字符 -->
</div>
{% endfor %}
{% else %}
<p>暂无文章,快去后台添加吧!</p>
{% endif %}
</body>
</html>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>{{ article.title }} - 我的博客</title>
</head>
<body>
<h1>{{ article.title }}</h1>
<p>发布时间:{{ article.pub_time|date:"Y-m-d H:i" }} | 作者:{{ article.author.username }}</p>
<hr>
<div>{{ article.content|linebreaks }}</div> <!-- linebreaks 转换换行符为 <br> -->
<br>
<a href="{% url 'article_list' %}">返回首页</a>
</body>
</html>
)添加几篇测试文章;,可看到文章列表;至此,一个简易的博客系统已完成,包含「后台管理+前台展示」核心功能。
Django 需配置静态文件目录,才能加载 CSS、JS、图片等资源。
在 blog 目录下创建 static/blog/ 目录,用于存放该应用的静态文件:
blog/
└── static/
└── blog/
├── css/
│ └── style.css # 自定义样式
└── images/
└── logo.png # 示例图片
打开 myfirstsite/settings.py,确认以下配置(默认已开启):
# 静态文件 URL 前缀
STATIC_URL = 'static/'
# 开发阶段静态文件目录(生产环境需收集到统一目录)
STATICFILES_DIRS = [
BASE_DIR / "static", # 项目级静态文件目录(可选)
]
修改 article_list.html,引入自定义 CSS:
{% load static %} <!-- 加载静态文件标签 -->
<head>
<meta charset="UTF-8">
<title>我的博客</title>
<!-- 引用静态 CSS 文件 -->
<link rel="stylesheet" href="{% static 'blog/css/style.css' %}">
</head>
<body>
<!-- 引用静态图片 -->
<img src="{% static 'blog/images/logo.png' %}" alt="博客logo" width="100">
<!-- 其余内容不变 -->
</body>
打开 blog/models.py,新增 Comment 模型:
class Comment(models.Model):
# 评论内容
content = models.TextField(verbose_name="评论内容")
# 评论时间
create_time = models.DateTimeField(auto_now_add=True, verbose_name="评论时间")
# 关联文章(一篇文章可有多个评论)
article = models.ForeignKey(Article, on_delete=models.CASCADE, related_name="comments", verbose_name="所属文章")
# 关联用户(可选,匿名评论可去掉)
author = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="评论者")
def __str__(self):
return f"{self.author.username} 评论:{self.content[:20]}"
class Meta:
verbose_name = "评论"
verbose_name_plural = "评论"
ordering = ["-create_time"]
执行数据库迁移:
python manage.py makemigrations
python manage.py migrate
在 blog 目录下创建 forms.py,编写表单验证:
from django import forms
from .models import Comment
class CommentForm(forms.ModelForm):
# 自定义表单字段(可选,用于调整显示)
content = forms.CharField(widget=forms.Textarea(attrs={"rows": 3, "placeholder": "请输入评论..."}), label="")
class Meta:
model = Comment # 基于 Comment 模型创建表单
fields = ["content"] # 只显示 content 字段
更新 blog/views.py 的 article_detail 视图,添加表单处理逻辑:
from .forms import CommentForm
def article_detail(request, article_id):
article = Article.objects.get(id=article_id)
# 处理评论提交
if request.method == "POST":
# 验证用户是否登录(未登录则跳转到登录页)
if not request.user.is_authenticated:
from django.shortcuts import redirect
return redirect(f"/admin/login/?next=/blog/{article_id}/")
# 绑定表单数据
form = CommentForm(request.POST)
if form.is_valid(): # 验证数据合法性
comment = form.save(commit=False) # 不立即保存到数据库
comment.article = article # 关联所属文章
comment.author = request.user # 关联评论者(当前登录用户)
comment.save() # 保存到数据库
# 刷新页面(避免重复提交)
from django.shortcuts import redirect
return redirect(f"/blog/{article_id}/")
else:
# GET 请求:初始化空表单
form = CommentForm()
# 查询该文章的所有评论
comments = article.comments.all()
return render(request, 'blog/article_detail.html', {
'article': article,
'form': form,
'comments': comments
})
更新 article_detail.html:
{% load static %}
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>{{ article.title }} - 我的博客</title>
<link rel="stylesheet" href="{% static 'blog/css/style.css' %}">
</head>
<body>
<h1>{{ article.title }}</h1>
<p>发布时间:{{ article.pub_time|date:"Y-m-d H:i" }} | 作者:{{ article.author.username }}</p>
<hr>
<div>{{ article.content|linebreaks }}</div>
<br>
<!-- 评论表单 -->
<h3>评论区</h3>
<form method="POST">
{% csrf_token %} <!-- Django 必加:防止跨站请求伪造 -->
{{ form.as_p }} <!-- 渲染表单 -->
<button type="submit">提交评论</button>
</form>
<!-- 评论列表 -->
{% if comments %}
<div style="margin-top: 20px;">
{% for comment in comments %}
<div style="margin: 10px 0; padding: 10px; background: #f9f9f9;">
<p><strong>{{ comment.author.username }}</strong> {{ comment.create_time|date:"Y-m-d H:i" }}</p>
<p>{{ comment.content|linebreaks }}</p>
</div>
{% endfor %}
</div>
{% endif %}
<br>
<a href="{% url 'article_list' %}">返回首页</a>
</body>
</html>
Django 内置完整的用户认证系统,无需手动实现登录/注册:
(Admin 自带);django.contrib.auth 模块的 login/logout 函数;request.user 判断用户是否登录,request.user.is_authenticated 返回布尔值。开发完成后,需调整配置适配生产环境:
pip install mysqlclient;settings.py 的数据库配置:DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'myfirstsite', # 数据库名
'USER': 'root', # MySQL 用户名
'PASSWORD': 'your_mysql_password', # MySQL 密码
'HOST': '127.0.0.1', # 数据库地址
'PORT': '3306', # 端口
'CHARSET': 'utf8mb4', # 字符集(支持emoji)
}
}
# settings.py
DEBUG = False # 生产环境必须关闭
ALLOWED_HOSTS = ['your_domain.com', 'www.your_domain.com'] # 允许访问的域名
python manage.py collectstatic # 将所有静态文件收集到 STATIC_ROOT 目录
报错:CSRF token missing or incorrect
原因:表单未加 {% csrf_token %};
解决:在 POST 表单中添加 {% csrf_token %} 标签。
报错:DoesNotExist: Article matching query does not exist
原因:访问了不存在的文章 ID;
解决:使用 get_object_or_404 替代 get:
from django.shortcuts import get_object_or_404
article = get_object_or_404(Article, id=article_id)
静态文件加载失败
原因:未配置 STATIC_URL 或未加载 {% load static %};
解决:确认 settings.py 配置,模板开头添加 {% load static %}。
Django 的生态足够支撑从个人博客到企业级电商平台的所有开发需求,掌握核心用法后,可结合实际项目持续进阶。