Django入门教程:搭建你的第一个Python网站
初识 Django:我的第一个 Python 网站成长记

大家好,我是某互联网公司的后端开发工程师,日常工作主要围绕高并发系统的架构与优化。说到 Django,我其实是从一个实际项目开始真正上手的——那时候我们团队要快速搭建一个内容管理平台(CMS),时间紧、任务重。老板说:“一周上线 Demo。” 同时,要求我们使用 Python 技术栈。
说实话,在那之前我对 Web 框架的理解还停留在“听过几个名词”的阶段,虽然知道 Flask 轻量,Tornado 异步,Django 全能,但没有深入实战过。最终选择 Django 的原因也很直接:它自带 ORM、Admin、用户权限体系、模板引擎……几乎把我们要用的功能都内置了。更重要的是,它的生态成熟、文档完善、社区活跃,对于我们这样的“临时拼装小队”来说,非常友好。
这篇文章就记录我从零到一搭建这个网站的过程,希望也能帮那些刚接触 Django 的小伙伴少走一些弯路。
项目背景:一次典型的内部系统开发

我们需要做一个内部使用的 CMS 平台,主要功能是:
- 支持多个编辑人员发布文章;
- 文章需要分类、标签、审核状态等字段;
- 需要有后台管理员界面,用于审核文章和管理用户;
- 前端展示页面要做基础样式,不复杂但得像样;
- 最关键的是,数据安全性不能忽视,哪怕这是个内部系统。
听起来需求不算特别复杂,但作为第一次独立使用 Django 的人,我还是踩了不少坑。下面我会从头讲起,尽量详细地记录每一步思考和实现过程。
项目搭建第一步:Django 初始化与结构规划

安装环境
首先肯定是要安装 Django。我当时用的是 Python 3.9+pip。
pip install django==4.2.5
然后创建项目骨架:
django-admin startproject cms_project .
执行完成后,你会看到目录结构大概是这样的:
cms_project/
├── manage.py
└── cms_project/
├── asgi.py
├── settings.py
├── urls.py
└── wsgi.py
接下来启动服务器:
python manage.py runserver
不出意外,就能访问 http://127.0.0.1:8000 看到 Django 默认的欢迎页。一切准备就绪!
创建 App 模块
在 Django 中,推荐将不同的功能拆分成多个 app。我们的 CMS 核心功能是文章管理,所以我新建了一个 articles app:
python manage.py startapp articles
同时别忘了在 settings.py 中添加这个 app 到 INSTALLED_APPS 列表里:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# 我们自己的模块
'articles',
]
数据库设计:安全与扩展性并重
既然要做 CMS,自然离不开数据库模型的设计。我一开始就决定使用 PostgreSQL,而不是默认的 SQLite。虽然本地开发可以先用 SQLite 快速验证,但一旦进入生产环境,还是更建议使用真正的关系型数据库。
配置数据库连接
修改 settings.py 中的 DATABASES 字段如下:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'cms_db',
'USER': 'cms_user',
'PASSWORD': 'your_password',
'HOST': 'localhost',
'PORT': '5432',
}
}
为了测试方便,我在本机搭了个简易的 PostgreSQL 实例,使用 Docker:
docker run --name some-postgres -e POSTGRES_USER=cms_user -e POSTGRES_PASSWORD=your_password -e POSTGRES_DB=cms_db -p 5432:5432 -d postgres
这样就可以快速拥有一个数据库服务。
模型设计
接下来就是定义 Article 数据模型,文件放在 articles/models.py:
from django.db import models
from django.contrib.auth.models import User
class Category(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Tag(models.Model):
name = models.CharField(max_length=50)
def __str__(self):
return self.name
class Article(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
author = models.ForeignKey(User, on_delete=models.CASCADE)
category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True, blank=True)
tags = models.ManyToManyField(Tag, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
is_published = models.BooleanField(default=False) # 是否通过审核
def __str__(self):
return self.title
这里有几个值得说明的设计点:
- 用户与文章的关系:使用 Django 内建的 User 模型,省去自己造轮子;
- 外键约束:category 使用
on_delete=models.SET_NULL来避免删除分类导致文章丢失; - 多对多关系处理:tag 是一个典型的多对多字段;
- 软删除考虑:其实可以加一个
is_deleted字段,不过这次因为时间紧张,暂时略过了,后面再升级; - 安全意识体现:没有允许任何人随意删数据,而是通过状态字段控制是否显示。
生成迁移文件 & 同步数据库
写完 model 后,记得同步数据库:
python manage.py makemigrations
python manage.py migrate
这个时候你就可以登录数据库看看表是否已经正确建立起来了。
管理后台搭建:快速成型的神器
Django 自带 admin 功能,我们只需要注册模型即可快速拥有管理界面。
注册模型到 Admin
打开 articles/admin.py,添加以下代码:
from django.contrib import admin
from .models import Article, Category, Tag
@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
list_display = ('title', 'author', 'created_at', 'is_published')
list_filter = ('is_published', 'category', 'tags')
search_fields = ('title', 'content')
admin.site.register(Category)
admin.site.register(Tag)
之后运行服务,访问 /admin 页面,可以看到已经出现对应的文章管理界面。
这时候我发现一个很现实的问题:默认的管理员后台对非技术人员不够友好。我们团队有部分产品经理也需要操作这个系统,他们并不熟悉 technical 字段,比如不知道怎么选分类,或者不知道“is_published”意味着什么。
改进:增加描述和友好的字段名
于是我对 Admin 类进行了调整:
@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
list_display = ('标题', '作者', '创建时间', '已发布')
list_filter = ('已发布', '分类', '标签')
search_fields = ('标题', '内容')
fieldsets = (
(None, {'fields': ('标题', '内容')}),
('分类信息', {'fields': ('分类', '标签')}),
('状态控制', {'fields': ('已发布',)}),
)
def get_queryset(self, request):
qs = super().get_queryset(request)
if request.user.is_superuser:
return qs
return qs.filter(author=request.user)
def save_model(self, request, obj, form, change):
if not obj.pk:
obj.author = request.user
super().save_model(request, obj, form, change)
其中我还做了几点改进:
- 给字段起中文名,提高可读性;
- 对普通用户进行数据隔离,只能看到自己的文章;
- 在保存时自动设置作者为当前用户。
这样一来,产品同学也能轻松上手了。
前端页面展示:模板 + 接口初探
我们虽然是后端主导,但作为一个完整的系统,前端展示当然也不能落下。
编写视图函数
在 articles/views.py 中新增一个展示文章列表的视图:
from django.shortcuts import render
from .models import Article
def article_list(request):
articles = Article.objects.filter(is_published=True).order_by('-created_at')
return render(request, 'articles/list.html', {'articles': articles})
接着配置 URL,在 urls.py 里加上路由:
from django.urls import path
from articles import views
urlpatterns = [
path('admin/', admin.site.urls),
path('articles/', views.article_list, name='article_list'),
]
然后创建 templates 目录,组织结构如下:
templates/
└── articles/
└── list.html
list.html 文件内容大致如下:
<!DOCTYPE html>
<html>
<head>
<title>文章列表</title>
</head>
<body>
<h1>已发布的文章</h1>
<ul>
{% for article in articles %}
<li><a href="#">{{ article.title }}</a></li>
{% endfor %}
</ul>
</body>
</html>
访问 /articles/ 就能看到文章列表了。
接口设计初探
除了网页展示,我们还提供了 JSON 格式的接口供其他服务调用。最简单的做法是直接在 view 中返回 JsonResponse:
from django.http import JsonResponse
from .models import Article
def api_article_list(request):
articles = Article.objects.filter(is_published=True).values('id', 'title', 'created_at')
return JsonResponse(list(articles), safe=False)
URL 配置类似:
path('api/articles/', views.api_article_list),
但这种写法很快遇到了瓶颈:随着功能增多,手动处理参数校验、分页、排序变得非常麻烦。
于是我们改用 Django REST Framework(DRF)来做 API 层,这又是另一篇经验总结了。简单提一下,有了 DRF,我们可以定义 Serializers 和 ViewSets,极大地提升了 API 开发效率,也更容易做权限控制。
上线部署:生产环境的小细节
使用 Gunicorn + Nginx 部署
开发完成之后,我们准备上线测试版。我选择了比较常规的方案:Gunicorn 作为 WSGI server,Nginx 反向代理。
安装依赖:
pip install gunicorn
然后在项目根目录下新建 gunicorn.conf.py:
bind = "127.0.0.1:8001"
workers = 3
timeout = 60
accesslog = "/var/log/cms/gunicorn_access.log"
errorlog = "/var/log/cms/gunicorn_error.log"
capture_output = True
loglevel = "info"
启动命令:
gunicorn -c gunicorn.conf.py cms_project.wsgi
Nginx 配置如下(简化版):
server {
listen 80;
server_name yourdomain.com;
location / {
proxy_pass http://127.0.0.1:8001;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location /static/ {
alias /path/to/static/;
}
}
别忘了收集静态文件:
python manage.py collectstatic
安全注意事项
部署的时候我也犯过几个错误,分享给大家:
- DEBUG 设置未关闭:Django 默认开启 DEBUG 模式,上线时必须设置
DEBUG=False,否则会泄露敏感信息; - Secret Key 暴露:不要硬编码在 settings.py 中,最好从环境变量中读取;
- CSRF 和 Session 设置:特别是跨域请求和 Cookie 安全相关;
- 权限最小化:数据库账号应该只具备必要权限;
- 日志监控:部署后务必监控日志,及时发现异常请求或报错。
总结与感悟:从一个小网站学到的大道理
现在回头看,那个“一周上线 Demo”的目标,实际上花了整整三周才勉强完成。并不是功能有多复杂,而是在真实的工作场景中,总会遇到各种意料之外的小问题:
- 第一天:连数据库都连不上,是因为 PostgreSQL 的权限配置没搞定;
- 第三天:前端渲染一直出错,原来是缓存太强,强制刷新没反应;
- 第五天:上线之后突然数据库连接池爆满,被迫紧急加索引;
- ……
但正是这些看似零碎的小事,才让我真正理解了一个“完整网站”的构建过程:不只是写几个 model 和 view,更重要的是要考虑稳定性、安全性、性能、可维护性。
如果你也在入门 Django,以下几个建议送给你:
- 从模仿开始,但不要盲从:官方文档是最好的老师,但一定要动手敲一遍,不能只看不动;
- 多看源码:Django 代码质量非常高,看懂一些内部机制会让你受益匪浅;
- 注意安全性,早些养成习惯:很多新手忽略 XSS、CSRF、SQL 注入等问题,结果上线后漏洞频出;
- 合理利用内置功能,别重复造轮子:尤其是权限管理、Admin、ORM 这些模块,能节省大量时间;
- 提前考虑部署问题:不要等到“上线前夜”才发现无法部署;
- 写好注释和文档,给未来的自己留条活路:代码易读性非常重要。
结语
这篇文字与其说是教程,不如说我在这段时间工作的“个人成长笔记”。也许你正在尝试学 Django,也许你在工作中也遇到过类似的挑战。无论你是初学者,还是想深入了解 Python Web 开发,我都希望这篇经历能对你有所帮助。
最后,愿每一个认真写代码的人,都能写出又快又好、安全可靠的系统。共勉!

评论 0