Django项目搭建全攻略:从虚拟环境到Admin后台的完整实践
2026/8/27 16:40:27 网站建设 项目流程

1. 从“Hello, World!”到“Hello, Django!”:为什么你的第一个Django项目总在环境上卡壳?

如果你刚学Python,或者已经用Flask写过几个小玩意儿,现在想试试更“重量级”的Django,大概率会在一开始就遇到一堆环境问题。不是pip install django报错,就是创建项目后python manage.py runserver跑不起来,又或者VSCode里一堆红色波浪线提示找不到模块。这太正常了,我刚开始的时候也一样,感觉还没开始写代码,就被环境配置劝退了。

其实,Django搭建的核心,远不止那几行命令。它更像是一次对Python项目开发环境的“标准化体检”。很多人卡壳,不是因为Django复杂,而是因为对Python的包管理、虚拟环境、项目结构这些基础概念理解不深,或者在不同操作系统(Windows/macOS/Linux)上操作有差异。今天,我们就抛开那些速成教程,从一个有多年Python开发经验的博主视角,手把手、无死角地走一遍Django项目的搭建全过程。我会把那些教程里一笔带过、但实际开发中至关重要的细节都掰开揉碎讲清楚,比如:为什么一定要用虚拟环境?不同Python版本对Django有什么影响?manage.py这个文件到底是个什么“神器”?以及如何配置VSCode,让它成为你开发Django的得力助手,而不是绊脚石。

我们的目标不仅仅是让服务器跑起来,而是搭建一个干净、可维护、便于团队协作和日后部署的Django项目基石。记住,好的开始是成功的一半,在Web开发领域,这句话尤其正确。

2. 环境奠基:虚拟环境、Python版本与包管理的“铁三角”

在动手敲django-admin startproject之前,我们必须把地基打牢。这个地基就是Python项目管理的“铁三角”:Python解释器版本、虚拟环境(Virtual Environment)和包管理工具pip。忽略任何一点,你的项目都可能在未来遇到“依赖地狱”。

2.1 Python版本选择:不是越新越好

首先,打开你的终端(Windows用CMD或PowerShell,macOS/Linux用Terminal),输入python --versionpython3 --version。你会看到一个版本号,比如Python 3.8.10Python 3.11.4

注意:很多系统默认安装了Python 2和Python 3。命令python可能指向Python 2,而python3指向Python 3。Django 3.x和4.x已不再支持Python 2,所以请务必确认你使用的是Python 3.6或更高版本。我强烈建议使用Python 3.8到3.11之间的一个长期支持(LTS)版本,它们在稳定性和社区支持上都有很好的平衡。Python 3.12虽然新,但一些第三方库可能还未完全适配。

为什么版本重要?Django本身对不同Python版本有兼容性要求。例如,Django 4.2支持Python 3.8, 3.9, 3.10, 3.11。如果你用Python 3.7,就无法安装Django 4.2。你可以通过 Django官方文档 查看版本对应关系。

2.2 虚拟环境(Virtualenv):项目的“隔离病房”

这是新手最容易忽略,也最重要的一步。虚拟环境可以为每个Python项目创建一套独立的解释器和包安装目录,避免项目间的包版本冲突。

想象一下这个场景:你项目A需要Django 3.2,项目B需要Django 4.1。如果没有虚拟环境,你全局只能安装一个版本,切换项目时就会报错。虚拟环境就是为每个项目建立的“隔离病房”,里面的“药品”(第三方包)互不干扰。

创建虚拟环境的两种主流方式:

  1. 使用venv(Python 3.3+内置)

    # 进入你的项目总目录(比如叫 dev) cd ~/dev # 创建一个名为 mydjango_env 的虚拟环境 python3 -m venv mydjango_env

    执行后,会在当前目录下生成一个mydjango_env文件夹,里面包含了独立的Python解释器和pip。

  2. 使用virtualenv(第三方工具,功能更强大): 首先需要安装:pip install virtualenv

    cd ~/dev virtualenv mydjango_env # 你也可以指定Python解释器版本 # virtualenv -p /usr/bin/python3.8 mydjango_env

激活虚拟环境:

  • Windows (CMD/PowerShell):
    # 在CMD中 mydjango_env\Scripts\activate.bat # 在PowerShell中(可能需要先设置执行策略) mydjango_env\Scripts\Activate.ps1
  • macOS/Linux (bash/zsh):
    source mydjango_env/bin/activate

激活成功后,你的命令行提示符前面会出现虚拟环境的名字,如(mydjango_env) ~/dev $。这意味着之后所有pip install操作都只影响这个环境。

退出虚拟环境,在任何系统下,只需输入:deactivate

实操心得:我习惯把虚拟环境目录命名为.venv,并在项目根目录下创建。这样命名清晰,且以点开头在部分系统下默认隐藏,不干扰项目文件视图。更重要的是,务必把.venv添加到你的.gitignore文件中,千万不要将虚拟环境提交到版本控制系统(如Git)!

2.3 包管理:用pip安装Django并固化依赖

虚拟环境激活后,我们就可以安全地安装Django了。

# 安装最新稳定版的Django pip install django # 安装指定版本的Django(推荐,避免未来版本升级导致意外) pip install django==4.2.7

安装完成后,验证一下:

python -m django --version # 应该输出 4.2.7 (或你安装的版本号)

关键一步:生成requirements.txt这是项目依赖的“清单”。在虚拟环境激活状态下,运行:

pip freeze > requirements.txt

这个命令会将当前环境下所有已安装的包及其精确版本号写入requirements.txt文件。以后在新的环境(比如同事的电脑或部署服务器)中,只需要运行pip install -r requirements.txt,就能一键复现完全相同的依赖环境。这是保证项目可重现性的生命线。

3. 项目骨架生成:startprojectstartapp的深度解析

环境准备好了,现在开始创建Django项目本身。这里有两个核心命令:django-admin startprojectpython manage.py startapp。它们生成的每一个文件都有其特定使命。

3.1 创建项目:理解mysite/manage.py

在虚拟环境激活的状态下,在你喜欢的位置(比如~/dev)执行:

django-admin startproject mysite

这行命令会创建一个名为mysite的目录,结构如下:

mysite/ manage.py mysite/ __init__.py settings.py urls.py asgi.py wsgi.py

重要概念:外层mysite/vs 内层mysite/

  • 外层mysite/:是你的项目容器目录。你可以把它重命名为任何你喜欢的名字(比如myproject),它只是一个文件夹。
  • 内层mysite/:是你的实际Python包,里面包含了项目的核心配置。它的名字是你在import语句中使用的Python包名。

manage.py:你的瑞士军刀这个文件是Django项目的命令行工具入口。不要修改它。你几乎所有的项目管理操作都将通过它进行:

  • python manage.py runserver:启动开发服务器。
  • python manage.py startapp blog:创建一个名为blog的应用。
  • python manage.py makemigrations&python manage.py migrate:管理数据库迁移。
  • python manage.py createsuperuser:创建管理员账号。

3.2 创建应用(App):Django的模块化哲学

Django推崇“可插拔”的应用设计。一个项目(Project)由多个应用(App)组成。每个应用是一个独立的模块,负责一个特定的功能,比如用户认证(auth)、博客(blog)、论坛(forum)等。

进入外层mysite目录,创建一个博客应用:

cd mysite python manage.py startapp blog

这会生成一个blog目录:

blog/ __init__.py admin.py apps.py migrations/ __init__.py models.py tests.py views.py

关键文件说明:

  • models.py:定义数据模型(数据库表结构)。
  • views.py:编写视图函数或类,处理业务逻辑。
  • admin.py:注册模型到Django自带的管理后台。
  • urls.py需要手动创建。定义该应用下的URL路由。

为什么要把项目拆成多个App?

  1. 解耦与复用:一个设计良好的App(比如一个用户系统)可以轻松移植到其他Django项目中。
  2. 代码组织清晰:功能边界明确,便于团队协作和维护。
  3. Django生态支持:很多优秀的第三方功能都是以App的形式提供的,你可以直接pip install然后添加到INSTALLED_APPS中。

创建完App后,必须在项目配置文件mysite/settings.py中的INSTALLED_APPS列表里注册它:

# mysite/settings.py INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', ... # 其他默认应用 'blog', # 添加你创建的应用名 ]

4. 开发服务器初探与基础配置调优

现在,让我们让项目“活”起来。

4.1 启动开发服务器并访问

在项目根目录(有manage.py的目录)下运行:

python manage.py runserver

你会看到类似这样的输出:

Watching for file changes with StatReloader Performing system checks... System check identified no issues (0 silenced). You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions. Run 'python manage.py migrate' to apply them. July 10, 2024 - 10:00:00 Django version 4.2.7, using settings 'mysite.settings' Starting development server at http://127.0.0.1:8000/ Quit the server with CONTROL-C.

忽略关于未应用迁移的警告(我们稍后处理)。打开浏览器,访问http://127.0.0.1:8000/。你应该能看到Django的“安装成功”火箭页面!

开发服务器的特点:

  • 自动重载:当你修改了Python代码并保存后,服务器会自动重启(大部分情况下),无需手动停止再启动。
  • 仅限开发:这个服务器性能和安全性都不足以用于生产环境。千万不要用它来对外提供服务。

4.2 初始配置调优:settings.py的几处关键修改

刚创建的项目配置是通用的,我们需要根据自己需求进行一些调整。打开mysite/settings.py

1. 配置数据库(默认为SQLite)Django默认使用SQLite,它是一个单文件数据库,非常适合开发和轻量级应用。对于初学者,完全可以使用它。配置已经在DATABASES设置中写好了。 如果你想使用PostgreSQL或MySQL,需要先安装对应的数据库适配器(如psycopg2-binarymysqlclient),然后修改DATABASES配置。这里我们先保持默认。

2. 语言和时区找到以下两行并修改,让管理界面变成中文,并使用中国时区。

LANGUAGE_CODE = 'zh-hans' # 中文 TIME_ZONE = 'Asia/Shanghai' # 亚洲/上海时区 USE_I18N = True USE_TZ = True # 建议设置为True,让Django处理时区感知的datetime对象

3. 静态文件与媒体文件路径(提前规划)在文件末尾添加:

import os # Static files (CSS, JavaScript, Images) STATIC_URL = 'static/' # 指定开发阶段收集静态文件的目录 STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')] # 需要手动创建static文件夹 # Media files (用户上传的文件) MEDIA_URL = 'media/' MEDIA_ROOT = os.path.join(BASE_DIR, 'media') # 需要手动创建media文件夹

然后在项目根目录(与manage.py同级)手动创建staticmedia文件夹。

4. 应用数据库迁移回到终端,按Ctrl+C停止服务器。然后运行以下命令来创建初始数据库表(针对INSTALLED_APPS中自带的admin, auth等应用):

python manage.py migrate

这个命令会根据migrations目录下的迁移文件,在SQLite数据库文件(db.sqlite3)中创建对应的表。完成后,再次启动服务器,之前的警告信息就会消失。

5. 第一个视图与URL配置:理解MVT中的V和C

Django采用MVT(Model-View-Template)模式,类似于MVC。现在我们来创建第一个页面,理解View(视图)和URL配置(Controller的一部分)是如何工作的。

5.1 在App中编写视图(View)

视图是一个Python函数(或类),它接收一个Web请求(HttpRequest对象),并返回一个Web响应(HttpResponse对象)。打开blog/views.py,写入:

from django.http import HttpResponse from django.shortcuts import render def index(request): """博客首页视图""" # 简单地返回一段HTML文本 return HttpResponse(""" <h1>欢迎来到我的博客!</h1> <p>这是用Django搭建的第一个页面。</p> <a href='/about/'>关于我</a> """) def about(request): """关于页面视图""" # 使用render函数返回一个渲染后的模板(稍后介绍模板) # 暂时先返回简单的HttpResponse return HttpResponse(""" <h2>关于这个博客</h2> <p>这是一个学习Django的实践项目。</p> <a href='/'>返回首页</a> """)

5.2 配置App级别的URL路由

blog目录下,创建一个新文件urls.py(这是手动创建的):

# blog/urls.py from django.urls import path from . import views # 从当前目录导入views模块 urlpatterns = [ path('', views.index, name='index'), # 将根路径映射到index视图 path('about/', views.about, name='about'), ]

这里,path('about/', ...)意味着当用户访问http://127.0.0.1:8000/blog/about/时,会触发about视图函数。name参数给这个URL模式起了一个别名,在模板和代码中可以通过这个名字反向解析出URL,非常有用。

5.3 将App的URL包含到项目主路由中

现在需要告诉项目,当访问以/blog/开头的URL时,应该去blog这个App的urls.py中查找具体的路由。修改项目根目录下的mysite/urls.py

# mysite/urls.py from django.contrib import admin from django.urls import path, include # 导入include函数 urlpatterns = [ path('admin/', admin.site.urls), path('blog/', include('blog.urls')), # 包含blog应用的URL配置 ]

include()函数就像是一个“路由分派器”,它把以blog/开头的URL请求,全部转交给blog.urls模块去处理。

5.4 测试你的第一个页面

保存所有文件,确保开发服务器正在运行(如果没有,运行python manage.py runserver)。在浏览器中访问:

  • http://127.0.0.1:8000/blog/:你应该看到“欢迎来到我的博客!”的首页。
  • http://127.0.0.1:8000/blog/about/:你应该看到“关于这个博客”页面。

点击页面上的链接,它们应该可以互相跳转。恭喜!你已经完成了Django中请求-响应循环最核心的部分:URL路由 -> 视图函数 -> HTTP响应

6. 模板与静态文件:让页面“活”起来

直接返回HTML字符串在视图中非常不灵活,也难以维护。Django使用模板系统(Template)来分离Python逻辑和HTML展示。同时,我们需要引入CSS、JavaScript和图片等静态文件。

6.1 创建模板目录与基础模板

首先,在blog应用目录下创建templates文件夹,再在templates下创建blog文件夹(这是Django的约定,为了避免不同App间模板名冲突)。结构如下:

blog/ templates/ blog/ base.html index.html about.html

基础模板base.html: 这是一个所有页面共享的骨架,使用Django模板语言(DTL)的块(block)标签。

<!DOCTYPE html> <html lang="zh-hans"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>{% block title %}我的Django博客{% endblock %}</title> {% load static %} <link rel="stylesheet" href="{% static 'blog/css/style.css' %}"> </head> <body> <header> <h1><a href="{% url 'index' %}">我的博客</a></h1> <nav> <a href="{% url 'index' %}">首页</a> <a href="{% url 'about' %}">关于</a> </nav> </header> <main> {% block content %} <!-- 子模板的内容会插入到这里 --> {% endblock %} </main> <footer> <p>© 2024 我的Django学习项目</p> </footer> <script src="{% static 'blog/js/main.js' %}"></script> </body> </html>

注意{% static 'path/to/file' %}标签,它是用来生成静态文件URL的。{% url 'index' %}则是通过我们在urls.py中定义的name来反向生成URL,这样即使URL模式改变了,模板中的链接也不会失效。

首页模板index.html

{% extends 'blog/base.html' %} {% block title %}首页 - 我的博客{% endblock %} {% block content %} <h2>最新文章</h2> <ul> <!-- 这里未来会从数据库动态获取文章列表 --> <li>文章标题1 (发布日期)</li> <li>文章标题2 (发布日期)</li> </ul> {% endblock %}

关于页面模板about.html

{% extends 'blog/base.html' %} {% block title %}关于我们{% endblock %} {% block content %} <h2>关于这个网站</h2> <p>这是一个使用Django 4.2搭建的博客系统,用于学习和实践Web开发。</p> {% endblock %}

6.2 修改视图以渲染模板

更新blog/views.py,使用render函数:

from django.shortcuts import render def index(request): """博客首页视图""" context = { 'page_title': '博客首页', # 未来这里可以传递从数据库查询的文章列表 } # render函数会自动在app的templates目录下寻找`blog/index.html` return render(request, 'blog/index.html', context) def about(request): """关于页面视图""" return render(request, 'blog/about.html')

6.3 配置并添加静态文件

在项目根目录的static文件夹下(我们之前在settings.py中配置的STATICFILES_DIRS指向的目录),创建应用相关的静态子目录:

static/ blog/ css/ style.css js/ main.js images/

一个简单的style.css示例:

/* static/blog/css/style.css */ body { font-family: sans-serif; line-height: 1.6; margin: 0; padding: 20px; max-width: 800px; margin: auto; background-color: #f4f4f4; } header { background: #35424a; color: white; padding: 1rem 0; text-align: center; } nav a { color: white; margin: 0 15px; text-decoration: none; } main { background: white; padding: 20px; margin-top: 20px; border-radius: 5px; }

6.4 收集静态文件(开发与生产)

在开发阶段,Django的runserver会自动从STATICFILES_DIRS和各个App的static子目录中提供静态文件。这就是为什么我们访问/static/blog/css/style.css能生效。

但在生产环境(使用Nginx、Apache等),为了提高性能,通常需要运行一个命令将分散的静态文件收集到一个统一的目录:

python manage.py collectstatic

这个命令会将所有静态文件复制到settings.py中定义的STATIC_ROOT目录中。在开发阶段,我们暂时不需要运行它。

现在刷新浏览器页面,你应该能看到应用了CSS样式的、结构清晰的博客页面了。页面有了共同的页眉、页脚和导航栏,这正是模板继承的威力。

7. 模型与Admin后台:用代码定义你的数据

Web应用的核心是数据。Django通过模型(Model)来定义数据结构,并通过强大的内置Admin后台来管理这些数据。

7.1 定义博客文章模型

打开blog/models.py,我们来定义一个简单的Post(文章)模型:

from django.db import models from django.utils import timezone from django.contrib.auth.models import User class Post(models.Model): """博客文章模型""" # 文章状态选项 STATUS_CHOICES = ( ('draft', '草稿'), ('published', '已发布'), ) title = models.CharField(max_length=200, verbose_name='标题') # Slug是一个短标签,用于生成友好的URL slug = models.SlugField(max_length=250, unique_for_date='publish', verbose_name='URL标识') # 外键关联到Django内置的用户模型 author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='blog_posts', verbose_name='作者') body = models.TextField(verbose_name='正文') # 发布时间 publish = models.DateTimeField(default=timezone.now, verbose_name='发布时间') # 创建时间(自动设置) created = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') # 更新时间(自动更新) updated = models.DateTimeField(auto_now=True, verbose_name='更新时间') # 文章状态 status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='draft', verbose_name='状态') class Meta: # 定义元数据 ordering = ('-publish',) # 默认按发布时间降序排列 verbose_name = '文章' # 在Admin后台显示的单数名称 verbose_name_plural = '文章' # 在Admin后台显示的复数名称 def __str__(self): # 定义对象的字符串表示,在Admin后台和shell中显示 return self.title

字段类型详解:

  • CharField:用于短文本,必须指定max_length
  • SlugField:一种特殊的CharField,通常只包含字母、数字、下划线或连字符,用于URL。
  • ForeignKey:定义多对一关系。on_delete=models.CASCADE表示当关联的User被删除时,其所有文章也被删除。related_name用于从User对象反向查询其文章。
  • TextField:用于长文本,不限长度。
  • DateTimeField:日期时间字段。auto_now_add=True只在创建时自动设置为当前时间;auto_now=True在每次保存时都更新为当前时间。
  • choices:提供一个可选值列表,在表单和Admin中会显示为下拉框。

7.2 创建并应用数据库迁移

模型定义好后,我们需要将其变化同步到数据库。这分为两步:

  1. 生成迁移文件:Django会比较模型和当前数据库状态的差异,并生成一个描述这个差异的Python脚本(迁移文件)。

    python manage.py makemigrations blog

    执行后,会在blog/migrations/目录下生成一个类似0001_initial.py的文件。永远不要手动编辑这个文件,除非你知道自己在做什么。

  2. 应用迁移:执行迁移文件中的指令,实际修改数据库(创建表、添加字段等)。

    python manage.py migrate

    这个命令会应用所有未应用的迁移,包括我们刚刚为blog应用生成的迁移。

7.3 将模型注册到Admin后台

Django的Admin后台是一个自动生成的、功能强大的数据管理界面。要让我们的Post模型出现在后台,需要在blog/admin.py中注册它。

from django.contrib import admin from .models import Post @admin.register(Post) # 使用装饰器注册 class PostAdmin(admin.ModelAdmin): """定制Post模型在Admin后台的显示""" # 列表页显示的字段 list_display = ('title', 'slug', 'author', 'publish', 'status') # 右侧过滤器 list_filter = ('status', 'created', 'publish', 'author') # 搜索框可搜索的字段 search_fields = ('title', 'body') # 根据slug字段自动填充title(需要设置prepopulated_fields) prepopulated_fields = {'slug': ('title',)} # 层级导航(日期) date_hierarchy = 'publish' # 默认排序 ordering = ('status', '-publish')

7.4 创建超级用户并登录Admin

首先,我们需要创建一个可以登录Admin后台的超级用户:

python manage.py createsuperuser

按照提示输入用户名、邮箱和密码。

然后,确保开发服务器正在运行,访问http://127.0.0.1:8000/admin/。用刚才创建的超级用户账号登录。你会看到Django默认的认证和授权模型(Groups, Users)以及我们刚刚注册的Posts(文章)模型。

点击“Posts”后面的“增加”,你就可以通过一个友好的表单界面来创建、编辑和删除博客文章了。所有我们在PostAdmin类中定义的定制(如列表显示、过滤、搜索)都会生效。这极大地简化了初期的数据管理工。

8. 视图进阶与数据展示:从数据库到网页

现在我们有数据了,接下来要做的就是将数据库中的文章动态地展示在网页上。这需要修改视图,让它从数据库中查询数据,并传递给模板。

8.1 修改首页视图以获取文章列表

更新blog/views.py中的index视图:

from django.shortcuts import render, get_object_or_404 from .models import Post def index(request): """博客首页视图,展示已发布的文章列表""" # 从数据库中获取所有状态为‘published’的文章,并按发布时间倒序排列 posts = Post.objects.filter(status='published').order_by('-publish') context = { 'page_title': '最新文章', 'posts': posts, # 将文章列表传递给模板 } return render(request, 'blog/index.html', context)

这里,Post.objects是一个管理器(Manager),它提供了与数据库交互的接口。filter()方法用于过滤数据,order_by()用于排序。'-publish'中的负号表示降序。

8.2 创建文章详情页视图

我们还需要一个视图来展示单篇文章的详情。在blog/views.py中添加:

def post_detail(request, year, month, day, post_slug): """ 文章详情页视图。 通过年、月、日和slug唯一确定一篇文章。 """ # 使用get_object_or_404便捷函数,如果找不到对象则返回404页面 post = get_object_or_404(Post, status='published', slug=post_slug, publish__year=year, publish__month=month, publish__day=day) context = { 'post': post, } return render(request, 'blog/post_detail.html', context)

这个视图函数接收四个参数(年、月、日、slug),这些参数将从URL中捕获。

8.3 更新URL配置

修改blog/urls.py,为详情页添加一个URL模式:

from django.urls import path from . import views urlpatterns = [ path('', views.index, name='index'), path('about/', views.about, name='about'), # 新的详情页URL,使用尖括号<>捕获参数 path('<int:year>/<int:month>/<int:day>/<slug:post_slug>/', views.post_detail, name='post_detail'), ]

URL模式中的<int:year>表示捕获一个整数并赋值给year参数,<slug:post_slug>表示捕获一个符合slug格式的字符串。

8.4 创建详情页模板并更新首页模板

首先创建详情页模板blog/templates/blog/post_detail.html

{% extends 'blog/base.html' %} {% block title %}{{ post.title }}{% endblock %} {% block content %} <article> <h2>{{ post.title }}</h2> <p class="meta"> 作者: {{ post.author }} | 发布时间: {{ post.publish|date:"Y年m月d日 H:i" }} | 最后更新: {{ post.updated|date:"Y年m月d日 H:i" }} </p> <div class="post-body"> {{ post.body|linebreaks }} </div> </article> <p><a href="{% url 'index' %}">返回文章列表</a></p> {% endblock %}

这里使用了Django模板过滤器(Filter):|date用于格式化日期,|linebreaks将文本中的换行符转换为HTML的<br><p>标签。

然后,更新首页模板blog/templates/blog/index.html,使其动态显示文章列表并链接到详情页:

{% extends 'blog/base.html' %} {% block title %}首页 - 我的博客{% endblock %} {% block content %} <h2>最新文章</h2> {% if posts %} <ul class="post-list"> {% for post in posts %} <li> <h3> <a href="{% url 'post_detail' year=post.publish.year month=post.publish.month day=post.publish.day post_slug=post.slug %}"> {{ post.title }} </a> </h3> <p class="meta"> 作者: {{ post.author }} | 发布于: {{ post.publish|date:"Y-m-d" }} | 状态: {{ post.get_status_display }} </p> <p>{{ post.body|truncatewords:30|linebreaks }}</p> <!-- 只显示前30个词 --> </li> {% endfor %} </ul> {% else %} <p>暂无已发布的文章。</p> {% endif %} {% endblock %}

注意{% url 'post_detail' ... %}的用法,我们传递了多个命名参数来反向生成详情页的URL。post.get_status_display会自动显示STATUS_CHOICES中对应的可读标签(“已发布”而不是“published”)。truncatewords过滤器用于截断长文本。

8.5 测试动态内容

  1. 登录Admin后台 (http://127.0.0.1:8000/admin/blog/post/)。
  2. 创建几篇状态为“published”的文章,并填写标题、slug和正文。
  3. 访问博客首页 (http://127.0.0.1:8000/blog/),你应该能看到文章列表。
  4. 点击任意一篇文章的标题链接,应该能跳转到该文章的详情页,URL格式类似于http://127.0.0.1:8000/blog/2024/07/10/my-first-post/

至此,一个具备基本CRUD(通过Admin后台)和展示功能的微型博客系统就搭建完成了。数据从数据库(Model)通过视图(View)查询,传递给模板(Template)渲染,最终呈现给用户,这就是Django MVT模式的完整流程。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询