目录
引言:从零开始构建属于自己的网站
一、为什么选 Django?先搞懂它的 “过人之处”
二、环境搭建:3 步搞定 Django 安装(附常见坑点)
步骤 1:安装 Python(已安装可跳过)
步骤 2:创建虚拟环境(新手必做!)
步骤 3:安装 Django
三、从 0 创建第一个 Django 项目:5 分钟跑通 “Hello World”
步骤 1:创建项目
步骤 2:创建应用(App)
步骤 3:注册应用
步骤 4:写一个简单的视图
步骤 5:配置 URL 路由
步骤 6:启动服务器,测试效果
四、核心概念详解:用 “餐厅” 类比理解 Django 的 MTV 架构
五、实战:开发个人博客核心功能(附完整代码)
阶段 1:设计数据模型(Model)
阶段 2:生成数据库表(迁移操作)
阶段 3:配置 Admin 后台,快速管理数据
步骤 1:创建超级管理员(登录 Admin 用)
步骤 2:注册模型到 Admin
步骤 3:登录 Admin 后台,添加测试数据
阶段 4:开发文章列表页(View+Template)
步骤 1:写视图函数(获取文章数据)
步骤 2:创建模板文件
步骤 3:配置列表页路由
阶段 5:开发文章详情页(View+Template)
步骤 1:写详情页视图
步骤 2:创建详情页模板
步骤 3:配置详情页路由
阶段 6:用模板继承优化页面(避免重复代码)
步骤 1:创建基础模板
步骤 2:修改列表页模板继承基础模板
步骤 3:修改详情页模板继承基础模板
六、静态文件处理:给博客加张封面图(CSS/JS/ 图片)
步骤 1:配置静态文件路径
步骤 2:创建静态文件目录并添加图片
步骤 3:在模板中引用静态文件
七、常见问题与解决方案(新手必看)
八、下一步学习:让博客更强大
总结:Django 为什么适合新手?
class 卑微码农:
def __init__(self):
self.技能 = ['能读懂十年前祖传代码', '擅长用Ctrl+C/V搭建世界', '信奉"能跑就别动"的玄学']
self.发量 = 100 # 初始发量
self.咖啡因耐受度 = '极限'
def 修Bug(self, bug):
try:
# 试图用玄学解决问题
if bug.严重程度 == '离谱':
print("这一定是环境问题!")
else:
print("让我看看是谁又没写注释...哦,是我自己。")
except Exception as e:
# 如果try块都救不了,那就...
print("重启一下试试?")
self.发量 -= 1 # 每解决一个bug,头发-1
# 实例化一个我
我 = 卑微码农()
引言:从零开始构建属于自己的网站
如果你是刚接触 Python Web 开发的新手,可能会有这样的困惑:“想做个网站,既要能存数据、有后台管理,又要考虑安全问题,难道要自己从零搭架构吗?”
其实不用。Django 早就帮我们把这些 “麻烦事” 打包好了 —— 这个被称为 “自带电池” 的框架,能让你用最少的代码快速搭建一个功能完整的网站。今天这篇文章,我会从安装到部署,带你亲手开发一个可上线的个人博客,全程避开晦涩概念,只讲实战干货,哪怕是编程新手也能跟着做。
一、为什么选 Django?先搞懂它的 “过人之处”
在学一个框架前,我们得先知道它能解决什么问题。我当初刚接触 Django 时,最直观的感受是:它把 Web 开发里的 “重复工作” 全做了,我们只用专注于业务逻辑。
举个例子:做网站肯定要存数据(比如用户信息、文章内容),如果不用框架,你得自己写 SQL 语句操作数据库,还得处理数据校验、防注入攻击;要做后台管理,得自己设计页面、写增删改查逻辑;要保障安全,得手动处理密码加密、防跨站请求伪造(CSRF)……
而 Django 呢?这些功能全内置了:
- 用 ORM(对象关系映射)替代 SQL,写 Python 代码就能操作数据库,不用记复杂的 SQL 语法;
- 自带 Admin 后台,配置几行代码就能生成可操作的管理界面,增删改查全搞定;
- 内置安全机制,自动处理 XSS、CSRF、密码哈希等问题,不用自己操心;
- 模板系统支持页面复用,写一次导航栏,全站都能调用。
简单说:用 Django 开发,你写的代码都是 “有价值的业务逻辑”,不用浪费时间在重复造轮子上。这也是为什么很多公司用它做电商、CMS、社交平台 —— 开发效率太高了。
二、环境搭建:3 步搞定 Django 安装(附常见坑点)
开始写代码前,先把环境搭好。这里以 “Windows 10+Python 3.9” 为例,macOS 和 Linux 步骤类似,最后会附差异说明。
步骤 1:安装 Python(已安装可跳过)
Django 是 Python 框架,所以必须先装 Python。官网(https://www.python.org/)下载对应版本,注意安装时勾选 “Add Python to PATH”(否则后续要手动配环境变量),然后一路 “Next” 完成安装。
验证是否安装成功:打开 cmd(Windows)或终端(macOS/Linux),输入python --version,能看到版本号就说明没问题。
步骤 2:创建虚拟环境(新手必做!)
为什么要建虚拟环境?因为不同项目可能依赖不同版本的库,比如 A 项目用 Django 3.2,B 项目用 Django 4.2,不隔离的话会冲突。
创建方法:
- 找个地方建个文件夹(比如
D:\django_blog),作为项目目录; - 打开 cmd,cd 到这个文件夹:
cd D:\django_blog; - 输入命令创建虚拟环境:
python -m venv venv(最后一个venv是环境名,可自定义); - 激活虚拟环境:
- Windows:
venv\Scripts\activate(激活后命令行前会出现(venv)); - macOS/Linux:
source venv/bin/activate。
- Windows:
步骤 3:安装 Django
激活虚拟环境后,直接用 pip 安装:pip install django==4.2(指定 4.2 版本,稳定且文档全)。
验证安装:输入django-admin --version,显示4.2.x就说明成功了。
坑点提醒:
- 如果报错 “pip 不是内部命令”,大概率是安装 Python 时没勾选 “Add to PATH”,重新安装并勾选即可;
- macOS/Linux 可能需要用
pip3替代pip,python3替代python(因为系统可能预装 Python 2)。
三、从 0 创建第一个 Django 项目:5 分钟跑通 “Hello World”
环境就绪后,我们先快速创建一个项目,感受下 Django 的 “开箱即用”。
步骤 1:创建项目
在虚拟环境激活的状态下,cd 到项目目录(比如D:\django_blog),输入命令:
django-admin startproject mysite
这个命令会创建一个名为mysite的文件夹,里面是 Django 项目的基础结构:
mysite/
├── manage.py # 项目管理脚本(启动服务、数据库迁移等都靠它)
└── mysite/ # 项目核心配置文件夹
├── __init__.py
├── asgi.py # 异步部署用(暂时不用管)
├── settings.py # 项目配置(数据库、时区等)
├── urls.py # 路由配置(URL和视图的映射)
└── wsgi.py # 同步部署用(暂时不用管)
步骤 2:创建应用(App)
Django 里 “项目(Project)” 是总容器,“应用(App)” 是具体功能模块(比如博客的 “文章模块”“用户模块”)。一个项目可以包含多个应用。
我们先创建一个 “博客” 应用,命名为blog:
- 先 cd 到
mysite文件夹(和manage.py同级):cd mysite; - 输入命令:
python manage.py startapp blog。
此时会生成blog文件夹,结构如下:
blog/
├── __init__.py
├── admin.py # 配置Admin后台
├── apps.py
├── migrations/ # 数据库迁移文件(自动生成)
├── models.py # 数据模型(定义数据库表)
├── tests.py # 测试代码
├── urls.py # 应用内的路由配置
└── views.py # 视图(处理业务逻辑)
步骤 3:注册应用
创建应用后,需要告诉 Django “有这个应用”。打开mysite/settings.py,找到INSTALLED_APPS列表,添加blog:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog', # 新增:注册blog应用
]
步骤 4:写一个简单的视图
视图是处理用户请求的地方。打开blog/views.py,写一个返回 “Hello World” 的视图:
from django.http import HttpResponse
# 定义视图函数:接收request参数(包含请求信息),返回响应
def hello(request):
return HttpResponse("Hello Django! 这是我的第一个页面~")
步骤 5:配置 URL 路由
用户访问http://xxx/hello时,要能触发上面的hello视图,这需要配置 URL 路由。
- 先在
blog应用里创建urls.py(默认没有),添加:
from django.urls import path
from . import views # 导入当前应用的views
# 路由列表:path(路径, 视图函数, 别名)
urlpatterns = [
path('hello/', views.hello, name='hello'),
]
- 再把应用的路由注册到项目总路由。打开
mysite/urls.py,修改为:
from django.contrib import admin
from django.urls import path, include # 新增include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('blog.urls')), # 新增:当访问根路径时,包含blog应用的urls
]
步骤 6:启动服务器,测试效果
在manage.py同级目录,输入命令启动开发服务器:
python manage.py runserver
看到 “Starting development server at http://127.0.0.1:8000/” 就说明成功了。打开浏览器访问http://127.0.0.1:8000/hello,会看到我们写的 “Hello Django! 这是我的第一个页面~”。
小技巧:开发时服务器会自动监听代码变化,改了代码不用重启,刷新页面就能看到效果(但改了settings.py这类配置文件需要重启)。
四、核心概念详解:用 “餐厅” 类比理解 Django 的 MTV 架构
刚才我们快速跑通了一个页面,但可能还是对 Django 的工作流程有点懵。Django 采用的是 MTV 架构(Model-Template-View),其实很好理解,我们用 “餐厅” 来类比:
- Model(模型):相当于 “后厨仓库”,负责数据的存储和管理(比如食材的种类、数量)。在 Django 里,模型对应数据库表,用 Python 类定义,不用直接写 SQL。
- Template(模板):相当于 “菜单”,负责页面的展示(比如菜名、图片、价格)。模板是 HTML 文件,支持嵌入 Python 变量和逻辑,让页面能动态显示数据。
- View(视图):相当于 “厨师”,负责处理业务逻辑(比如根据订单把食材做成菜)。视图接收用户请求,调用模型获取数据,再传给模板渲染成最终页面。
再加上URL 路由(相当于 “服务员”,负责把客人引导到对应厨师),整个流程就是:
用户访问 URL → 路由找到对应视图 → 视图调用模型拿数据 → 视图把数据传给模板 → 模板渲染页面返回给用户。
理解了这个流程,接下来我们开发博客的核心功能就会很清晰。
五、实战:开发个人博客核心功能(附完整代码)
我们的目标是做一个能发布文章、展示列表、查看详情的博客,包含以下功能:
- 设计数据模型(存储文章、分类、标签);
- 实现文章列表页和详情页;
- 用 Admin 后台管理文章;
- 美化页面(模板继承 + CSS)。
阶段 1:设计数据模型(Model)
博客最核心的数据是 “文章”,一篇文章通常有标题、内容、发布时间、分类、标签等信息。我们在blog/models.py里定义这些模型:
from django.db import models
from django.utils import timezone # 处理时间
# 分类模型
class Category(models.Model):
name = models.CharField(max_length=100, verbose_name="分类名称") # 字符串类型,最长100字符
created_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间") # 自动记录创建时间
def __str__(self):
return self.name # 后台显示分类名称
class Meta:
verbose_name = "分类" # 后台显示的模型名称
verbose_name_plural = verbose_name # 复数形式(中文不用变)
# 标签模型
class Tag(models.Model):
name = models.CharField(max_length=50, verbose_name="标签名称")
created_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
def __str__(self):
return self.name
class Meta:
verbose_name = "标签"
verbose_name_plural = verbose_name
# 文章模型
class Article(models.Model):
title = models.CharField(max_length=200, verbose_name="标题")
content = models.TextField(verbose_name="内容") # 长文本,适合存文章内容
created_time = models.DateTimeField(default=timezone.now, verbose_name="发布时间") # 默认当前时间
# 外键:一篇文章属于一个分类,一个分类可以有多个文章(一对多关系)
category = models.ForeignKey(Category, on_delete=models.CASCADE, verbose_name="分类")
# 多对多:一篇文章可以有多个标签,一个标签可以对应多篇文章
tags = models.ManyToManyField(Tag, blank=True, verbose_name="标签") # blank=True表示可以为空
def __str__(self):
return self.title # 后台显示文章标题
class Meta:
verbose_name = "文章"
verbose_name_plural = verbose_name
ordering = ['-created_time'] # 按发布时间倒序排列(新文章在前)
模型字段说明:
-
CharField:短文本(如标题、分类名),必须指定max_length; -
TextField:长文本(如文章内容),不用指定长度; -
DateTimeField:时间字段,auto_now_add=True表示创建时自动记录,default=timezone.now表示默认当前时间; -
ForeignKey:一对多关系(如文章→分类); -
ManyToManyField:多对多关系(如文章→标签)。
阶段 2:生成数据库表(迁移操作)
定义好模型后,需要把它转换成数据库表。Django 的迁移(migrations)功能会自动帮我们做这件事,不用写 SQL。
-
生成迁移文件:
python manage.py makemigrations此时blog/migrations文件夹会生成一个0001_initial.py,记录模型的变化。 -
执行迁移(创建表):
python manage.py migrate这一步会根据迁移文件在数据库中创建表。Django 默认用 SQLite 数据库(无需额外配置,适合开发),文件是mysite/db.sqlite3。
小知识:如果后续修改了模型(比如新增字段),需要重新执行makemigrations和migrate,Django 会智能处理变更,不会删除已有数据。
阶段 3:配置 Admin 后台,快速管理数据
Django 最强大的功能之一就是自带 Admin 后台,配置好后可以直接增删改查数据,不用自己写管理页面。
步骤 1:创建超级管理员(登录 Admin 用)
执行命令:python manage.py createsuperuser,按提示输入用户名、邮箱、密码(密码输入时不显示,输完回车即可)。
步骤 2:注册模型到 Admin
打开blog/admin.py,把我们定义的Article、Category、Tag注册进去:
from django.contrib import admin
from .models import Article, Category, Tag
# 自定义Article的Admin显示
class ArticleAdmin(admin.ModelAdmin):
# 列表页显示的字段
list_display = ('title', 'category', 'created_time')
# 可搜索的字段
search_fields = ('title', 'content')
# 过滤器(按分类、时间筛选)
list_filter = ('category', 'created_time')
# 注册模型(第二个参数是自定义配置,可选)
admin.site.register(Article, ArticleAdmin)
admin.site.register(Category)
admin.site.register(Tag)
步骤 3:登录 Admin 后台,添加测试数据
启动服务器python manage.py runserver,访问http://127.0.0.1:8000/admin,用超级管理员账号登录。
此时会看到我们注册的 “文章”“分类”“标签”,点击 “Add” 可以添加测试数据(比如添加 2 个分类、3 个标签、5 篇文章),后面开发页面会用到这些数据。
阶段 4:开发文章列表页(View+Template)
列表页需要展示所有文章的标题、发布时间、分类等信息,点击标题可进入详情页。
步骤 1:写视图函数(获取文章数据)
打开blog/views.py,新增index视图,用于获取所有文章并传给模板:
from django.shortcuts import render
from .models import Article # 导入Article模型
# 首页/文章列表页
def index(request):
# 获取所有文章(按created_time倒序,模型里已配置ordering)
articles = Article.objects.all()
# 把数据传给模板:第一个参数是request,第二个是模板路径,第三个是字典(键是模板中用的变量名,值是数据)
return render(request, 'blog/index.html', {'articles': articles})
步骤 2:创建模板文件
Django 的模板需要放在应用名/templates/应用名/目录下(固定规范,避免不同应用模板冲突)。
- 新建目录:在
blog文件夹下依次创建templates/blog(即blog/templates/blog/); - 在该目录下创建
index.html,内容如下:
<!DOCTYPE html>
<html lang="zh-***">
<head>
<meta charset="UTF-8">
<title>我的博客</title>
<style>
/* 简单美化样式 */
body {
max-width: 800px;
margin: 0 auto;
padding: 20px;
font-family: "微软雅黑", sans-serif;
}
.article {
margin-bottom: 30px;
padding-bottom: 20px;
border-bottom: 1px solid #eee;
}
.title {
font-size: 20px;
margin: 10px 0;
}
.title a {
color: #333;
text-decoration: none;
}
.title a:hover {
color: #2a7ae2;
}
.meta {
color: #666;
font-size: 14px;
}
.content {
margin-top: 10px;
line-height: 1.6;
}
</style>
</head>
<body>
<h1>我的博客</h1>
<!-- 循环显示所有文章 -->
{% for article in articles %}
<div class="article">
<div class="title">
<!-- 链接到详情页,{% url 'detail' article.id %} 表示通过别名'detail'的路由,传入文章id -->
<a href="{% url 'detail' article.id %}">{{ article.title }}</a>
</div>
<div class="meta">
发布时间:{{ article.created_time|date:"Y-m-d H:i" }} |
分类:{{ article.category.name }}
</div>
<div class="content">
<!-- 只显示前200字作为摘要 -->
{{ article.content|truncatechars:200 }}
</div>
</div>
{% empty %}
<!-- 如果没有文章,显示提示 -->
<p>暂无文章,敬请期待~</p>
{% endfor %}
</body>
</html>
模板里的{% %}是 Django 模板标签,{{ }}是变量:
-
{% for article in articles %}:循环遍历文章列表; -
{{ article.title }}:显示文章标题; -
{{ article.created_time|date:"Y-m-d H:i" }}:用date过滤器格式化时间; -
{% url 'detail' article.id %}:根据路由别名detail生成详情页 URL,传入文章 id。
步骤 3:配置列表页路由
打开blog/urls.py,添加index视图的路由:
urlpatterns = [
path('hello/', views.hello, name='hello'),
path('', views.index, name='index'), # 根路径对应index视图
]
此时访问http://127.0.0.1:8000/,就能看到文章列表了(如果之前在 Admin 添加了数据)。
阶段 5:开发文章详情页(View+Template)
详情页需要展示单篇文章的完整内容,包括标题、时间、分类、标签、全文。
步骤 1:写详情页视图
在blog/views.py中新增detail视图,根据文章 id 获取单篇文章:
from django.shortcuts import render, get_object_or_404 # 新增get_object_or_404
from .models import Article
# 文章详情页
def detail(request, article_id):
# get_object_or_404:如果找不到对应id的文章,返回404错误
article = get_object_or_404(Article, id=article_id)
return render(request, 'blog/detail.html', {'article': article})
detail视图接收article_id参数(从 URL 中获取),用于定位具体文章。
步骤 2:创建详情页模板
在blog/templates/blog/下创建detail.html:
<!DOCTYPE html>
<html lang="zh-***">
<head>
<meta charset="UTF-8">
<title>{{ article.title }} - 我的博客</title>
<style>
body {
max-width: 800px;
margin: 0 auto;
padding: 20px;
font-family: "微软雅黑", sans-serif;
}
.title {
font-size: 24px;
text-align: center;
margin: 20px 0;
}
.meta {
text-align: center;
color: #666;
margin-bottom: 30px;
padding-bottom: 10px;
border-bottom: 1px solid #eee;
}
.content {
line-height: 1.8;
font-size: 16px;
}
.tags {
margin-top: 20px;
padding-top: 10px;
border-top: 1px solid #eee;
}
.tag {
display: inline-block;
background: #f0f0f0;
padding: 3px 8px;
margin-right: 5px;
border-radius: 4px;
font-size: 14px;
}
.back {
margin-top: 30px;
}
.back a {
color: #2a7ae2;
text-decoration: none;
}
</style>
</head>
<body>
<div class="title">{{ article.title }}</div>
<div class="meta">
发布时间:{{ article.created_time|date:"Y-m-d H:i" }} |
分类:{{ article.category.name }}
</div>
<div class="content">
{{ article.content|linebreaks }} <!-- linebreaks过滤器:将换行符转为<br>或<p> -->
</div>
<div class="tags">
标签:
{% for tag in article.tags.all %}
<span class="tag">{{ tag.name }}</span>
{% empty %}
<span>无标签</span>
{% endfor %}
</div>
<div class="back">
<a href="{% url 'index' %}">← 返回首页</a>
</div>
</body>
</html>
步骤 3:配置详情页路由
在blog/urls.py中添加详情页路由:
urlpatterns = [
path('hello/', views.hello, name='hello'),
path('', views.index, name='index'),
# <int:article_id> 表示从URL中获取整数类型的article_id,传给detail视图
path('article/<int:article_id>/', views.detail, name='detail'),
]
现在点击列表页的文章标题,就能跳转到详情页了。
阶段 6:用模板继承优化页面(避免重复代码)
现在列表页和详情页的 HTML 有很多重复(比如头部样式、导航),如果要改样式,两个页面都得改,很麻烦。Django 的模板继承可以解决这个问题:定义一个 “基础模板”,其他模板继承它并修改差异部分。
步骤 1:创建基础模板
在blog/templates/blog/下创建base.html:
<!DOCTYPE html>
<html lang="zh-***">
<head>
<meta charset="UTF-8">
<title>{% block title %}我的博客{% endblock %}</title> <!-- 标题块:子模板可覆盖 -->
<style>
body {
max-width: 800px;
margin: 0 auto;
padding: 20px;
font-family: "微软雅黑", sans-serif;
}
header {
border-bottom: 2px solid #333;
padding-bottom: 10px;
margin-bottom: 20px;
}
.site-title {
margin: 0;
font-size: 28px;
}
.site-title a {
color: #333;
text-decoration: none;
}
footer {
margin-top: 50px;
text-align: center;
color: #666;
border-top: 1px solid #eee;
padding-top: 10px;
}
</style>
{% block extra_css %}{% endblock %} <!-- 额外CSS块:子模板可添加样式 -->
</head>
<body>
<header>
<h1 class="site-title"><a href="{% url 'index' %}">我的博客</a></h1>
</header>
<main>
{% block content %}{% endblock %} <!-- 内容块:子模板的主要内容 -->
</main>
<footer>
<p>© 2024 我的博客 | 用Django搭建</p>
</footer>
</body>
</html>
模板中{% block 名称 %}{% endblock %}是 “块”,子模板可以通过{% block 名称 %}覆盖这些部分。
步骤 2:修改列表页模板继承基础模板
修改index.html:
{% extends 'blog/base.html' %} <!-- 继承基础模板 -->
{% block title %}文章列表 - 我的博客{% endblock %} <!-- 覆盖标题块 -->
{% block extra_css %}
<!-- 列表页额外样式 -->
<style>
.article {
margin-bottom: 30px;
padding-bottom: 20px;
border-bottom: 1px solid #eee;
}
.title {
font-size: 20px;
margin: 10px 0;
}
.title a {
color: #333;
text-decoration: none;
}
.title a:hover {
color: #2a7ae2;
}
.meta {
color: #666;
font-size: 14px;
}
.content {
margin-top: 10px;
line-height: 1.6;
}
</style>
{% endblock %}
{% block content %}
<!-- 覆盖内容块:列表页的具体内容 -->
{% for article in articles %}
<div class="article">
<div class="title">
<a href="{% url 'detail' article.id %}">{{ article.title }}</a>
</div>
<div class="meta">
发布时间:{{ article.created_time|date:"Y-m-d H:i" }} |
分类:{{ article.category.name }}
</div>
<div class="content">
{{ article.content|truncatechars:200 }}
</div>
</div>
{% empty %}
<p>暂无文章,敬请期待~</p>
{% endfor %}
{% endblock %}
步骤 3:修改详情页模板继承基础模板
修改detail.html:
{% extends 'blog/base.html' %}
{% block title %}{{ article.title }} - 我的博客{% endblock %}
{% block extra_css %}
<!-- 详情页额外样式 -->
<style>
.title {
font-size: 24px;
text-align: center;
margin: 20px 0;
}
.meta {
text-align: center;
color: #666;
margin-bottom: 30px;
padding-bottom: 10px;
border-bottom: 1px solid #eee;
}
.content {
line-height: 1.8;
font-size: 16px;
}
.tags {
margin-top: 20px;
padding-top: 10px;
border-top: 1px solid #eee;
}
.tag {
display: inline-block;
background: #f0f0f0;
padding: 3px 8px;
margin-right: 5px;
border-radius: 4px;
font-size: 14px;
}
.back {
margin-top: 30px;
}
.back a {
color: #2a7ae2;
text-decoration: none;
}
</style>
{% endblock %}
{% block content %}
<div class="title">{{ article.title }}</div>
<div class="meta">
发布时间:{{ article.created_time|date:"Y-m-d H:i" }} |
分类:{{ article.category.name }}
</div>
<div class="content">
{{ article.content|linebreaks }}
</div>
<div class="tags">
标签:
{% for tag in article.tags.all %}
<span class="tag">{{ tag.name }}</span>
{% empty %}
<span>无标签</span>
{% endfor %}
</div>
<div class="back">
<a href="{% url 'index' %}">← 返回首页</a>
</div>
{% endblock %}
现在两个页面都继承了base.html的头部和底部,修改基础模板就能同时影响所有页面,大幅减少重复代码。
六、静态文件处理:给博客加张封面图(CSS/JS/ 图片)
网站通常需要用到图片、自定义 CSS、JS 等静态文件,Django 有专门的静态文件管理机制。我们以给博客加一张封面图为例,演示如何处理静态文件。
步骤 1:配置静态文件路径
打开mysite/settings.py,找到静态文件相关配置(默认已存在):
# 静态文件URL前缀(模板中引用时用)
STATIC_URL = 'static/'
# 开发时静态文件存放的目录(需要手动创建)
STATICFILES_DIRS = [
BASE_DIR / 'static', # BASE_DIR是项目根目录(mysite)
]
步骤 2:创建静态文件目录并添加图片
- 在
mysite目录(和manage.py同级)创建static文件夹; - 在
static下创建images文件夹,放入一张图片(比如cover.jpg)。
目录结构如下:
mysite/
├── static/
│ └── images/
│ └── cover.jpg # 封面图
├── manage.py
└── ...
步骤 3:在模板中引用静态文件
修改base.html,在头部添加封面图。需要先加载静态文件标签{% load static %},然后用{% static '路径' %}引用:
{% load static %} <!-- 加载静态文件标签 -->
<!DOCTYPE html>
<html lang="zh-***">
<head>
<!-- 省略其他内容 -->
</head>
<body>
<header>
<h1 class="site-title"><a href="{% url 'index' %}">我的博客</a></h1>
<!-- 引用封面图 -->
<img src="{% static 'images/cover.jpg' %}" alt="博客封面" style="width:100%; max-height:300px; object-fit:cover;">
</header>
<!-- 省略其他内容 -->
</body>
</html>
刷新页面,就能看到封面图了。如果图片不显示,检查路径是否正确(比如文件名是否大小写错误)。
七、常见问题与解决方案(新手必看)
开发过程中难免遇到问题,这里整理几个新手常踩的坑及解决方法:
-
“TemplateDoesNotExist” 错误原因:模板路径不对。Django 默认找
应用名/templates/应用名/下的模板,确保目录结构正确(比如blog/templates/blog/index.html)。 -
Admin 后台看不到模型原因:忘记在
admin.py中注册模型,或注册时写错模型名。检查admin.site.register(Article)是否正确。 -
数据库迁移报错 “no such table”原因:没执行迁移命令。先执行
python manage.py makemigrations,再执行python manage.py migrate。 -
静态文件不加载原因:开发时需要配置
STATICFILES_DIRS,且模板中必须用{% static %}标签引用,不能直接写相对路径。
八、下一步学习:让博客更强大
目前我们实现了博客的核心功能,但 Django 的能力远不止这些。想进一步完善,可以学习:
-
用户系统:用 Django 内置的
django.contrib.auth实现注册、登录、权限管理(比如只有登录用户能发文章); - 评论功能:新增评论模型,在详情页添加评论表单;
-
搜索功能:用
Q对象实现文章标题 / 内容搜索; - 部署上线:把网站部署到云服务器(如阿里云、腾讯云),用 Nginx+Gunicorn 配置生产环境;
- Django REST framework:把博客改造成 API 接口,支持移动端调用。
总结:Django 为什么适合新手?
回顾整个开发过程,我们用几十行代码就实现了一个有数据存储、后台管理、页面展示的博客,这在没有框架的情况下几乎不可能。Django 的 “自带电池” 理念,让新手不用纠结底层细节,能快速看到成果 —— 这种 “成就感” 正是持续学习的动力。
如果你是刚入门 Web 开发的新手,建议先跟着本文敲一遍代码,感受 Django 的便捷;熟悉后再深入学习 ORM、中间件、信号等高级特性。记住:编程的核心是解决问题,框架只是工具,能高效实现需求的工具就是好工具。
祝你在 Django 的学习路上少走弯路,早日开发出自己的网站!