Django 入门教程:从零开始开发 Web 应用2

2025年10月10日 00:38

六、模板(Templates):如何展示动态内容?

1. 什么是模板?为什么需要它?

模板是包含 HTML 代码和特殊模板语法的文件,用于生成动态网页。它的作用是:
  • 分离 HTML 代码和 Python 代码,使前后端分离
  • 可以重用 HTML 结构(如导航栏、页脚)
  • 支持动态内容替换,根据不同数据展示不同内容

2. 模板的工作原理

Django 模板系统的工作流程:
  1. 视图函数准备好需要展示的数据
  2. 视图函数调用render()函数,指定模板文件和数据
  3. Django 模板引擎加载模板文件,替换其中的模板变量和标签
  4. 生成最终的 HTML,返回给用户

3. 创建模板文件

Django 推荐的模板存放结构是在应用目录下创建templates文件夹,再在里面创建与应用同名的文件夹(避免模板名冲突)。
  1. blog目录下创建templates文件夹
  2. templates文件夹下创建blog文件夹
  3. blog文件夹下创建home.html文件:
html
预览
<!-- blog/templates/blog/home.html -->
<!DOCTYPE html>
<html>
<head>
    <title>我的博客</title>
</head>
<body>
    <h1>欢迎来到我的博客!</h1>
    <p>今天是:{{ today }}</p>
</body>
</html>
  • {{ today }}是模板变量,会被视图传递的实际数据替换

4. 在视图中使用模板

修改blog/views.py,使用模板展示动态内容:
python
运行
from django.shortcuts import render
from datetime import datetime

def home(request):
    # 准备要传递给模板的数据
    context = {
        'today': datetime.now().strftime('%Y年%m月%d日'),
    }
    # render()函数会加载模板,替换变量,并返回HttpResponse
    return render(request, 'blog/home.html', context)
  • render()函数的三个参数:
    • request:请求对象
    • 模板路径(blog/home.html对应blog/templates/blog/home.html
    • context:一个字典,包含要传递给模板的数据
现在访问http://127.0.0.1:8000/blog/,你会看到当前日期被动态显示出来。

5. 模板继承:避免重复代码

模板继承可以让你创建一个基础模板,然后在其他模板中重用它,避免重复编写相同的 HTML 代码(如导航栏、页脚)。
  1. 创建基础模板blog/templates/blog/base.html
html
预览
<!-- blog/templates/blog/base.html -->
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>{% block title %}我的博客{% endblock %}</title>
</head>
<body>
    <header>
        <h1><a href="{% url 'blog_home' %}">我的博客</a></h1>
        <nav>
            <a href="{% url 'blog_home' %}">首页</a>
        </nav>
    </header>
    
    <main>
        {% block content %}{% endblock %}
    </main>
    
    <footer>
        <p>&copy; {% now "Y" %} 我的博客</p>
    </footer>
</body>
</html>
  • {% block 名称 %}:定义一个可被继承模板覆盖的块
  • {% url 'blog_home' %}:使用 URL 的名称生成 URL,避免硬编码
  1. 修改home.html继承基础模板:
html
预览
<!-- blog/templates/blog/home.html -->
{% extends 'blog/base.html' %}

{% block title %}首页 - 我的博客{% endblock %}

{% block content %}
    <h2>欢迎来到我的博客!</h2>
    <p>今天是:{{ today }}</p>
{% endblock %}
  • {% extends %}:指定要继承的基础模板
  • 只需要填充block中的内容,其他部分会自动继承

七、模型(Models):如何存储和管理数据?

1. 什么是模型?为什么需要它?

模型是 Django 中用于表示数据库表的 Python 类。它的作用是:
  • 定义数据的结构和类型
  • 提供数据库操作的方法,无需编写 SQL
  • 实现数据验证和业务逻辑
Django 的 ORM(对象关系映射)系统会自动将模型转换为数据库表,将模型的属性转换为表的字段。

2. 创建第一个模型

我们来创建一个Article模型,表示博客文章:
编辑blog/models.py
python
运行
from django.db import models
from django.utils import timezone

class Article(models.Model):
    # 文章标题,最大长度100
    title = models.CharField(max_length=100)
    # 文章内容,长文本
    content = models.TextField()
    # 发布时间,默认为当前时间
    published_time = models.DateTimeField(default=timezone.now)
    
    # 定义对象的字符串表示
    def __str__(self):
        return self.title
这个模型会在数据库中创建一个名为blog_article的表,包含titlecontentpublished_time三个字段。

3. 模型字段类型详解

Django 提供了多种字段类型,用于存储不同类型的数据:
  1. CharField:短文本字段
    python
    运行
    title = models.CharField(max_length=100)  # 必须指定max_length
    
  2. TextField:长文本字段,用于存储大量文本
    python
    运行
    content = models.TextField()
    
  3. DateTimeField:日期时间字段
    python
    运行
    # auto_now_add: 创建时自动设置为当前时间,之后不会改变
    created_time = models.DateTimeField(auto_now_add=True)
    
    # auto_now: 每次保存时自动更新为当前时间
    updated_time = models.DateTimeField(auto_now=True)
    
    # default: 设置默认值
    published_time = models.DateTimeField(default=timezone.now)
    
  4. DateField:日期字段(只包含年、月、日)
    python
    运行
    birthday = models.DateField()
    
  5. TimeField:时间字段(只包含时、分、秒)
    python
    运行
    meeting_time = models.TimeField()
    
  6. IntegerField:整数字段
    python
    运行
    age = models.IntegerField()
    
  7. FloatField:浮点数字段
    python
    运行
    weight = models.FloatField()
    
  8. DecimalField:高精度小数字段,适合存储货币等需要精确计算的数据
    python
    运行
    price = models.DecimalField(max_digits=10, decimal_places=2)
    
    • max_digits:总位数
    • decimal_places:小数位数
  9. BooleanField:布尔值字段(True/False)
    python
    运行
    is_published = models.BooleanField(default=False)
    
  10. EmailField:电子邮件字段,会自动验证格式
    python
    运行
    email = models.EmailField()
    
  11. URLField:URL 字段,会自动验证格式
    python
    运行
    website = models.URLField()
    
  12. ForeignKey:外键,用于建立多对一关系
    python
    运行
    # 假设我们有一个Category模型
    category = models.ForeignKey('Category', on_delete=models.CASCADE)
    
    • on_delete=models.CASCADE:当关联的对象被删除时,该对象也被删除
  13. ManyToManyField:多对多关系
    python
    运行
    tags = models.ManyToManyField('Tag')
    

4. 数据库迁移:将模型同步到数据库

修改模型后,需要执行 "迁移" 操作,将模型的变化同步到数据库中。
  1. 生成迁移文件:
    bash
    python manage.py makemigrations
    
    这会在blog/migrations目录下生成一个迁移文件,记录模型的变化。
  2. 应用迁移:
    bash
    python manage.py migrate
    
    这会执行迁移文件中的 SQL 语句,实际修改数据库。
每次修改模型(添加字段、修改字段类型等)后,都需要执行这两个命令。

八、管理界面:快速管理你的数据

Django 提供了一个自动生成的管理界面,让你可以轻松管理数据库中的数据。

1. 创建超级用户

首先需要创建一个管理员账号:
bash
python manage.py createsuperuser
按照提示输入用户名、电子邮件和密码(密码输入时不会显示)。

2. 注册模型到管理界面

编辑blog/admin.py,将Article模型注册到管理界面:
python
运行
from django.contrib import admin
from .models import Article

# 注册Article模型
admin.site.register(Article)

3. 自定义管理界面

可以自定义模型在管理界面中的显示方式:
python
运行
from django.contrib import admin
from .models import Article

class ArticleAdmin(admin.ModelAdmin):
    # 列表页显示的字段
    list_display = ('title', 'published_time')
    # 可搜索的字段
    search_fields = ('title', 'content')
    # 过滤条件
    list_filter = ('published_time',)

# 注册模型和自定义类
admin.site.register(Article, ArticleAdmin)

4. 使用管理界面

启动开发服务器,访问http://127.0.0.1:8000/admin/,使用你创建的超级用户登录。
你可以:
  • 点击 "Articles" 进入文章管理页面
  • 点击 "Add" 添加新文章
  • 编辑或删除已有的文章

九、完善博客应用:将所有组件结合起来

让我们完善博客应用,实现文章列表和详情页功能。

1. 更新视图

修改blog/views.py
python
运行
from django.shortcuts import render, get_object_or_404
from django.utils import timezone
from .models import Article

def home(request):
    # 获取所有文章,按发布时间倒序排列
    articles = Article.objects.all().order_by('-published_time')
    context = {
        'today': timezone.now().strftime('%Y年%m月%d日'),
        'articles': articles
    }
    return render(request, 'blog/home.html', context)

def article_detail(request, article_id):
    # 获取指定ID的文章,如果不存在则返回404错误
    article = get_object_or_404(Article, pk=article_id)
    context = {
        'article': article
    }
    return render(request, 'blog/article_detail.html', context)

2. 更新 URL 配置

修改blog/urls.py
python
运行
from django.urls import path
from . import views

urlpatterns = [
    path('', views.home, name='blog_home'),
    # 文章详情页,<int:article_id>表示接收一个整数作为文章ID
    path('article/<int:article_id>/', views.article_detail, name='article_detail'),
]

3. 创建文章详情页模板

创建blog/templates/blog/article_detail.html
html
预览
{% extends 'blog/base.html' %}

{% block title %}{{ article.title }} - 我的博客{% endblock %}

{% block content %}
    <article>
        <h2>{{ article.title }}</h2>
        <p class="published-time">发布时间:{{ article.published_time|date:"Y年m月d日 H:i" }}</p>
        <div class="content">
            {{ article.content|linebreaks }}  {# linebreaks过滤器将换行符转换为<br><p>标签 #}
        </div>
    </article>
    <p><a href="{% url 'blog_home' %}">返回首页</a></p>
{% endblock %}

4. 更新首页模板

修改blog/templates/blog/home.html
html
预览
{% extends 'blog/base.html' %}

{% block title %}首页 - 我的博客{% endblock %}

{% block content %}
    <h2>欢迎来到我的博客!</h2>
    <p>今天是:{{ today }}</p>
    
    <h3>最新文章</h3>
    {% if articles %}
        <ul class="article-list">
            {% for article in articles %}
                <li>
                    <h4>
                        <a href="{% url 'article_detail' article.id %}">
                            {{ article.title }}
                        </a>
                    </h4>
                    <p class="published-time">
                        发布时间:{{ article.published_time|date:"Y年m月d日" }}
                    </p>
                    <p class="summary">
                        {{ article.content|truncatechars:100 }}  {# 只显示前100个字符 #}
                    </p>
                </li>
            {% endfor %}
        </ul>
    {% else %}
        <p>暂无文章,敬请期待!</p>
    {% endif %}
{% endblock %}

5. 测试完整功能

  1. 访问管理界面http://127.0.0.1:8000/admin/,添加几篇测试文章
  2. 访问博客首页http://127.0.0.1:8000/blog/,查看文章列表
  3. 点击文章标题,进入文章详情页

十、总结与下一步学习

通过本教程,你已经掌握了 Django 的核心概念和基本用法:
  • 理解了 Django 的项目和应用结构
  • 学会了创建视图和配置 URL 路由
  • 掌握了模板的使用和继承
  • 了解了模型的定义和各种字段类型
  • 学会了使用管理界面管理数据
  • 完成了一个简单但完整的博客应用
下一步可以学习:
  1. Django 表单:处理用户输入
  2. 用户认证:实现注册、登录功能
  3. 静态文件:添加 CSS、JavaScript 和图片
  4. 高级模型操作:复杂查询、关系处理
  5. 部署:将应用发布到互联网
Django 官方文档(https://docs.djangoproject.com/)是学习的最佳资源,建议深入阅读。
祝你在 Django 的学习道路上取得进步!