从 0 到 1 开发 Django 网站:小白也能上手的实战指南

从 0 到 1 开发 Django 网站:小白也能上手的实战指南

目录

引言:从零开始构建属于自己的网站

一、为什么选 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,不隔离的话会冲突。

创建方法:

  1. 找个地方建个文件夹(比如D:\django_blog),作为项目目录;
  2. 打开 cmd,cd 到这个文件夹:cd D:\django_blog
  3. 输入命令创建虚拟环境:python -m venv venv(最后一个venv是环境名,可自定义);
  4. 激活虚拟环境:
    • Windows:venv\Scripts\activate(激活后命令行前会出现(venv));
    • macOS/Linux:source venv/bin/activate

步骤 3:安装 Django

激活虚拟环境后,直接用 pip 安装:pip install django==4.2(指定 4.2 版本,稳定且文档全)。

验证安装:输入django-admin --version,显示4.2.x就说明成功了。

坑点提醒

  • 如果报错 “pip 不是内部命令”,大概率是安装 Python 时没勾选 “Add to PATH”,重新安装并勾选即可;
  • macOS/Linux 可能需要用pip3替代pippython3替代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

  1. 先 cd 到mysite文件夹(和manage.py同级):cd mysite
  2. 输入命令: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 路由。

  1. 先在blog应用里创建urls.py(默认没有),添加:
from django.urls import path
from . import views  # 导入当前应用的views

# 路由列表:path(路径, 视图函数, 别名)
urlpatterns = [
    path('hello/', views.hello, name='hello'),
]
  1. 再把应用的路由注册到项目总路由。打开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 → 路由找到对应视图 → 视图调用模型拿数据 → 视图把数据传给模板 → 模板渲染页面返回给用户。

理解了这个流程,接下来我们开发博客的核心功能就会很清晰。

五、实战:开发个人博客核心功能(附完整代码)

我们的目标是做一个能发布文章、展示列表、查看详情的博客,包含以下功能:

  1. 设计数据模型(存储文章、分类、标签);
  2. 实现文章列表页和详情页;
  3. 用 Admin 后台管理文章;
  4. 美化页面(模板继承 + 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。

  1. 生成迁移文件:python manage.py makemigrations此时blog/migrations文件夹会生成一个0001_initial.py,记录模型的变化。

  2. 执行迁移(创建表):python manage.py migrate这一步会根据迁移文件在数据库中创建表。Django 默认用 SQLite 数据库(无需额外配置,适合开发),文件是mysite/db.sqlite3

小知识:如果后续修改了模型(比如新增字段),需要重新执行makemigrationsmigrate,Django 会智能处理变更,不会删除已有数据。

阶段 3:配置 Admin 后台,快速管理数据

Django 最强大的功能之一就是自带 Admin 后台,配置好后可以直接增删改查数据,不用自己写管理页面。

步骤 1:创建超级管理员(登录 Admin 用)

执行命令:python manage.py createsuperuser,按提示输入用户名、邮箱、密码(密码输入时不显示,输完回车即可)。

步骤 2:注册模型到 Admin

打开blog/admin.py,把我们定义的ArticleCategoryTag注册进去:

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/应用名/目录下(固定规范,避免不同应用模板冲突)。

  1. 新建目录:在blog文件夹下依次创建templates/blog(即blog/templates/blog/);
  2. 在该目录下创建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:创建静态文件目录并添加图片

  1. mysite目录(和manage.py同级)创建static文件夹;
  2. 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>

刷新页面,就能看到封面图了。如果图片不显示,检查路径是否正确(比如文件名是否大小写错误)。

七、常见问题与解决方案(新手必看)

开发过程中难免遇到问题,这里整理几个新手常踩的坑及解决方法:

  1. “TemplateDoesNotExist” 错误原因:模板路径不对。Django 默认找应用名/templates/应用名/下的模板,确保目录结构正确(比如blog/templates/blog/index.html)。

  2. Admin 后台看不到模型原因:忘记在admin.py中注册模型,或注册时写错模型名。检查admin.site.register(Article)是否正确。

  3. 数据库迁移报错 “no such table”原因:没执行迁移命令。先执行python manage.py makemigrations,再执行python manage.py migrate

  4. 静态文件不加载原因:开发时需要配置STATICFILES_DIRS,且模板中必须用{% static %}标签引用,不能直接写相对路径。

八、下一步学习:让博客更强大

目前我们实现了博客的核心功能,但 Django 的能力远不止这些。想进一步完善,可以学习:

  • 用户系统:用 Django 内置的django.contrib.auth实现注册、登录、权限管理(比如只有登录用户能发文章);
  • 评论功能:新增评论模型,在详情页添加评论表单;
  • 搜索功能:用Q对象实现文章标题 / 内容搜索;
  • 部署上线:把网站部署到云服务器(如阿里云、腾讯云),用 Nginx+Gunicorn 配置生产环境;
  • Django REST framework:把博客改造成 API 接口,支持移动端调用。

总结:Django 为什么适合新手?

回顾整个开发过程,我们用几十行代码就实现了一个有数据存储、后台管理、页面展示的博客,这在没有框架的情况下几乎不可能。Django 的 “自带电池” 理念,让新手不用纠结底层细节,能快速看到成果 —— 这种 “成就感” 正是持续学习的动力。

如果你是刚入门 Web 开发的新手,建议先跟着本文敲一遍代码,感受 Django 的便捷;熟悉后再深入学习 ORM、中间件、信号等高级特性。记住:编程的核心是解决问题,框架只是工具,能高效实现需求的工具就是好工具。

祝你在 Django 的学习路上少走弯路,早日开发出自己的网站!

 

转载请说明出处内容投诉
CSS教程网 » 从 0 到 1 开发 Django 网站:小白也能上手的实战指南

发表评论

欢迎 访客 发表评论

一个令你着迷的主题!

查看演示 官网购买