搭建你的第一个 Python 网站:我的 Django 实战经验分享
引言:为何选择 Django?

三年前,我接手了一个小型的内部管理系统项目。当时公司需要快速上线一个用于审批流程和数据管理的平台,时间紧任务重。作为刚转行不久的后端开发工程师,我必须在有限时间内快速搭建出一个稳定、可扩展的网站。经过技术选型比较之后,我最终选择了 Django —— 因为它内置了 ORM、模板引擎、认证系统等一整套开箱即用的功能,非常适合这种“快、稳、准”的场景。
从那以后,我在多个项目中使用 Django 构建 Web 应用,包括企业门户、CRM、数据分析仪表盘等不同类型的产品。Django 也在不断迭代中变得越来越成熟,特别是在异步视图、REST API 支持、性能优化等方面都有了显著提升。
今天我想通过这篇实战性的入门文章,结合自己过去几年的实际开发经历,带你一步步搭建起你的第一个 Django 网站,并在这个过程中,聊聊我是怎么踩坑、避坑、再填坑的。
项目背景:我们准备做什么?

假设你现在是一个创业公司的后端负责人,你们正准备启动一个新产品——一个简单的 在线书评社区网站。用户可以在上面发布评论、点赞书籍、关注其他用户并查看他们的动态。
目标:
- 使用 Django 快速搭建基础网站结构
- 实现核心功能:注册/登录、书评发布、首页展示、搜索等功能
- 架构设计上保证可扩展性和安全性
- 部署到线上环境运行
接下来我会以第一人称的方式带大家完成整个过程。
搭建第一步:创建 Django 项目和 App
首先安装 Django(确保你已经安装好 Python3.8+ 和 pip):
pip install django
创建项目:
django-admin startproject bookreview .
注意点:
startproject后面加一个.是为了将生成的配置文件放在当前目录下,而不是单独新建一个同名文件夹。
进入项目根目录,创建一个名为 reviews 的 app 来处理书评相关逻辑:
python manage.py startapp reviews
然后别忘了把这个 app 添加到项目的 INSTALLED_APPS 列表里,在 settings.py 文件中加入 'reviews'。
核心挑战之一:如何合理设计数据库模型?
作为一个刚接触 Django 的新手,最容易犯的错误就是“先写代码,不考虑数据结构”。这会导致后期迁移时频繁修改 model、造成大量重复工作。
所以我的建议是:先把数据库模型设计清楚!
我们的项目中有几个核心对象:
- 用户(User)✅ Django 已经提供了用户系统 ✅
- 书籍(Book)
- 书评(Review)
- 点赞(Like)
于是我在 models.py 中定义如下结构:
from django.db import models
from django.contrib.auth.models import User
class Book(models.Model):
title = models.CharField(max_length=200)
author = models.CharField(max_length=150)
published_date = models.DateField()
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
class Review(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
book = models.ForeignKey(Book, on_delete=models.CASCADE)
content = models.TextField()
rating = models.PositiveSmallIntegerField(default=3) # 评分 1~5
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['-created_at']
class Like(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
review = models.ForeignKey(Review, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
unique_together = ('user', 'review')
这段代码有几个值得强调的点:
- 我们使用了
ForeignKey建立关联关系,这样便于后续查询与聚合操作 - 对
Like表设置了unique_together,防止同一用户给同一个评论多次点赞 - 所有字段都加上了合适的类型和长度限制,避免未来做迁移时手忙脚乱
接着执行数据库迁移命令:
python manage.py makemigrations
python manage.py migrate
挑战二:前后端分离还是模板渲染?这是个问题!

这个问题其实也是我在实际项目中最纠结的一环。现在很多项目都采用前后端分离架构,比如 Vue + Django REST Framework。但如果是初创项目或者 MVP(Minimum Viable Product),我通常会优先选择 Django 自带的模板系统,原因如下:
- 开发速度快,无需同时维护两个工程
- 路由管理更统一
- SEO 友好(模板渲染天然支持 SSR)
当然如果你打算做一个 SPA 或者已经有前端团队,那推荐用 DRF + JWT 搭建接口服务,后面也会提到这块内容。
本次我们采用 Django 内置的模板系统来实现页面渲染。
开始编码:构建页面与逻辑交互
我们先来实现一个最简单的功能:显示所有书籍的列表页。
步骤一:URL 设计
编辑 urls.py,引入 views 并添加路由:
from django.urls import path
from reviews import views
urlpatterns = [
path('', views.index, name='index'),
]
步骤二:编写视图函数
在 views.py 中实现 index 视图:
from django.shortcuts import render
from .models import Book
def index(request):
books = Book.objects.all().order_by('-published_date')[:10]
return render(request, 'reviews/index.html', {'books': books})
步骤三:创建 HTML 模板
创建 templates/reviews/index.html:
<!DOCTYPE html>
<html>
<head>
<title>书评社区</title>
</head>
<body>
<h1>最近出版的图书</h1>
<ul>
{% for book in books %}
<li>
{{ book.title }} by {{ book.author }}
({{ book.published_date|date:"Y-m-d" }})
</li>
{% endfor %}
</ul>
</body>
</html>
然后记得告诉 Django 模板的路径,在 settings.py 中找到:
TEMPLATES = [
{
...
'DIRS': [BASE_DIR / 'templates'],
...
}
]
这样我们就完成了首页的基本展示功能。
更复杂功能:用户注册与登录
这部分内容虽然 Django 提供了一定的支持,但在实际使用中依然需要额外处理一些细节,比如:
- 注册时密码校验
- 邮件验证用户是否真实
- 登录失败次数限制
实现用户注册视图:
这里我们可以借助 UserCreationForm 类来简化工作:
from django.contrib.auth.forms import UserCreationForm
from django.urls import reverse_lazy
from django.views import generic
class RegisterView(generic.CreateView):
form_class = UserCreationForm
success_url = reverse_lazy('login')
template_name = 'registration/register.html'
并添加对应的 URL:
path('register/', views.RegisterView.as_view(), name='register'),
模板文件 registration/register.html:
<h2>注册</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">提交</button>
</form>
是不是超级方便?Django 默认已经集成了安全防护机制,比如 CSRF Token、密码哈希处理等。不过,我们还需要考虑用户体验上的优化,例如:
- 在注册页面增加邮箱输入框
- 发送激活邮件以确认账户有效性(可以使用
django-allauth第三方插件实现)
性能优化初探:数据库查询优化
在一次性能测试中我发现首页加载特别慢,排查发现是:
books = Book.objects.all().order_by('-published_date')[:10]
这一句导致每次请求都要全表扫描,效率极低。
解决方案也很简单 —— 给 published_date 字段加上索引:
class Book(models.Model):
...
published_date = models.DateField(db_index=True)
然后重新 makemigrations && migrate。这样一来,排序查询速度提升了几十倍,页面加载从原来的 1.2s 缩短到了 0.15s。
Tip: 对于经常被用来排序或过滤的字段,一定要加上索引;但也不要过度滥用,因为会影响写入性能。
小坑提醒:静态资源处理 & 部署配置
本地调试没问题,部署到服务器就报错“找不到 CSS 文件”?这几乎是我第一次上线时遇到最多的问题。
解决方式很简单,但容易忽略:
- 设置 STATIC_ROOT:
STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR / 'staticfiles'
- 运行收集静态资源命令:
python manage.py collectstatic
- 在 Nginx 或 Apache 中正确设置
/static/目录的访问权限
此外,记得在生产环境中禁用 DEBUG 模式:
DEBUG = False
ALLOWED_HOSTS = ['yourdomain.com']
否则可能会暴露敏感信息,带来安全隐患。
扩展思路:为将来留余地
随着业务发展,我们的书评社区可能需要提供更多 API 接口,比如:
- 获取某本书的所有评论
- 提供移动端调用的 JSON 接口
- 支持第三方社交账号登录
这时候就可以集成 Django REST Framework(DRF) 来构建 RESTful API:
安装:
pip install djangorestframework
配置 settings.py:
INSTALLED_APPS += ['rest_framework']
简单例子:返回书籍列表的 API:
from rest_framework import viewsets
from .models import Book
from .serializers import BookSerializer
class BookViewSet(viewsets.ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
然后通过 router 注册即可对外提供 /api/books/ 接口。
这套模式也适用于后续接入小程序、App、或者其他微服务组件,非常灵活。
效果总结:我们得到了什么?
通过这个实践项目,我不仅熟悉了 Django 的基本架构,还掌握了以下几个关键能力:
- 如何快速搭建一个完整网站原型
- 数据库模型设计的基本方法
- 基于类视图的高级用法(如通用视图、混入类)
- 安全性与性能的基础保障手段
- 如何为未来扩展打下良好基础
更重要的是,我养成了先设计再编码、边做边记录的好习惯。这些经验后来在我参与更大规模的项目时,起到了至关重要的作用。
最后一点小建议:少走弯路的几点忠告
版本控制是王道。哪怕你是单兵作战,请养成良好的 Git 使用习惯。每个小功能提交一次 commit,分支管理清晰,方便回滚和协作。
善用官方文档和社区资源。Django 社区非常活跃,几乎每个问题都能找到答案。Google + Stack Overflow + 官方文档,是你的最佳组合拳。
前期多花时间在结构设计上,比后期重构成本要低得多。特别是数据库模型,宁可在写代码前画几张草图,也别拍脑袋写代码。
多写测试。别怕麻烦,写单元测试不仅能帮你发现 bug,还能让你更好地理解代码逻辑。Django 提供了很好的测试框架支持。
保持对新技术的关注。Django 正在积极拥抱 async,你可以尝试在合适的地方使用异步视图,提升响应速度。
结语:Django 是你成长路上的好伙伴
Django 不仅是个框架,更是帮助你快速落地产品、理解 Web 开发本质的工具。它不是万能的,但它足够健壮,足以支撑你的每一个想法。
如果你是刚开始学习后端开发的新人,我强烈建议你以 Django 作为起点。它的生态系统丰富、文档完善、社区友好,非常适合边学边练。
希望这篇文章对你有所启发,也欢迎你在评论区留言交流自己的实践经验。让我们一起在代码的世界里越走越远吧!

评论 0