从“Hello World”到上线部署:用Django搭建我的第一个Python网站实战总结
开篇:为什么是Django?

我在一家中型互联网公司担任后端开发工程师,主要负责数据平台和内部系统的开发与维护。虽然日常工作中更多使用Go或Node.js构建高并发的服务,但在一些中小项目、快速验证场景下,我更倾向于使用Django——Python生态中最成熟、最稳定的Web框架之一。
去年我们部门需要搭建一个面向内容运营的后台管理系统(CMS),用于管理文章发布、活动配置和基础数据分析。团队成员技术栈参差不齐,且时间紧迫,我们需要在两周内交付原型并启动迭代。这时候,Django凭借其“开箱即用”的特性、ORM的强大易用性以及完善的Admin系统,成了我们技术选型的重点。
这篇文章将结合我那次项目的实际经历,手把手带你完成一个简单的Django项目搭建,并分享我在这个过程中踩过的坑和收获的经验。
项目背景:为什么选择用Django做这个项目?

我们当时要做的系统其实功能并不复杂:
- 运营同学可以新增/编辑文章
- 设置文章封面图和状态(草稿 / 发布)
- 管理活动页面的基本信息(标题、描述、开始结束时间等)
- 统计每日文章数量和点击量
之所以没有选用现成的WordPress之类的内容管理工具,是因为我们希望系统能更好地接入公司内部的权限系统、用户中心服务,以及后续的分析系统。
最终我们的团队决定采用Django + Bootstrap的方式搭建一套轻量级CMS后台,目标是:
- 快速出原型并可直接上生产环境跑;
- 提供API供前端调用(前后端分离的雏形);
- 后期方便扩展统计模块和其他业务模块。
搭建过程:一步步从零开始
Step 1:准备开发环境
首先创建虚拟环境:
python -m venv venv
source venv/bin/activate
然后安装Django:
pip install django
查看当前版本是否符合预期:
django-admin --version
建议使用稳定版,比如我现在用的是 Django 4.2 LTS 版本,因为我们要部署到生产环境,LTS版本在安全性上有保障。
Step 2:创建项目结构
接下来,生成基本项目骨架:
django-admin startproject cms_project
cd cms_project
python manage.py runserver
默认会开启本地服务器监听8000端口,访问 http://localhost:8000 就可以看到 Django 的欢迎页了。说明你的基础环境搭建成功!
但还不能满足我们的需求,我们还需要创建自己的应用(application)。Django推荐每个功能模块是一个app,所以这里我们创建两个app:一个是文章管理(articles),一个是活动管理(activities)。
python manage.py startapp articles
python manage.py startapp activities
记得在 cms_project/settings.py 中添加这两个应用到 INSTALLED_APPS 里:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'articles',
'activities',
]
Step 3:设计数据库模型(Articles)
以文章为例,我们在 articles/models.py 中定义 Article 类:
from django.db import models
from django.contrib.auth.models import User
class Article(models.Model):
STATUS_CHOICES = (
('draft', 'Draft'),
('published', 'Published'),
)
title = models.CharField(max_length=255)
content = models.TextField()
cover_image = models.ImageField(upload_to='covers/')
author = models.ForeignKey(User, on_delete=models.CASCADE)
status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='draft')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
接着执行迁移:
python manage.py makemigrations
python manage.py migrate
此时你会在本地看到 db.sqlite3 文件,这是Django默认的SQLite数据库,适合本地开发调试。当然在正式环境中我们肯定不会用它,后面会讲生产环境配置。
Step 4:注册Admin后台
Django自带的Admin系统真的非常强大,特别是在快速搭建后台的时候简直是神器。
打开 articles/admin.py,加入以下代码:
from django.contrib import admin
from .models import Article
@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
list_display = ('title', 'author', 'status', 'created_at')
list_filter = ('status', 'created_at')
search_fields = ('title', 'content')
prepopulated_fields = {'slug': ('title',)}
这时运行一下 server:
python manage.py runserver
访问 http://localhost:8000/admin,你就能看到文章的管理界面了!是不是超级快?
不过要注意几点:
默认用户名密码是在数据库中存储的,需要用命令创建管理员:
python manage.py createsuperuser如果你在公司有统一的身份认证系统,比如OAuth2或者LDAP,可能需要自己集成SSO登陆系统,这部分我们后面再展开。
Step 5:开发RESTful接口
虽说Django本身是MVC框架,但为了支持未来前端调用API的需求,我们采用了 Django REST framework (DRF) 来开发REST API。
安装 DRF:
pip install djangorestframework
同样在 settings.py 添加:
INSTALLED_APPS += ['rest_framework']
然后写一个简单的文章接口(views.py):
from rest_framework import viewsets
from .models import Article
from .serializers import ArticleSerializer
class ArticleViewSet(viewsets.ModelViewSet):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
还要写一个序列化器(serializers.py):
from rest_framework import serializers
from .models import Article
class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = '__all__'
最后,在主URL中引入路由(cms_project/urls.py):
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from articles.views import ArticleViewSet
router = DefaultRouter()
router.register(r'articles', ArticleViewSet)
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include(router.urls)),
]
现在你可以访问 /api/articles/ 接口了。GET、POST、PUT、DELETE 都已经支持!
不过这只是个起点,真正上线时还需要考虑分页、过滤、权限控制等内容。我们后面会提到这些要点。
遇到的问题与挑战
尽管Django为我们提供了很多开箱即用的功能,但在实际部署和使用过程中也遇到了不少问题,以下是我遇到的几个典型挑战:
挑战一:图片上传路径配置
我们在开发环境上传图片没问题,但上了测试环境发现找不到图片。后来排查发现,我们用的 ImageField 默认会把文件保存在项目根目录下的指定路径,而生产环境静态文件是通过Nginx处理的,没设置好就会404。
解决方法:设置MEDIA_ROOT和MEDIA_URL:
# settings.py
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
并在urls.py中临时启用媒体文件服务(仅限开发环境):
from django.conf.urls.static import static
from django.conf import settings
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
生产环境则通过Nginx配置代理:
location /media {
alias /path/to/media;
}
挑战二:数据库性能瓶颈
随着文章数量增加到上千条,列表展示速度明显变慢。起初我们用了默认的 Article.objects.all() 做查询,结果导致大量不必要的JOIN操作。
解决方案:
- 使用
select_related()或prefetch_related()减少SQL查询次数 - 对搜索字段加上索引(尤其是text类型,不要忘记创建GIN索引)
- 分页处理(限制单页展示数目)
挑战三:跨域请求问题
前后端分离后,前端页面部署在另一个域名下,第一次发请求就报错 CORS。
解决方式:使用 django-cors-headers 插件来统一处理CORS问题。
安装:
pip install django-cors-headers
添加中间件:
MIDDLEWARE = [
...
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
...
]
CORS_ORIGIN_ALLOW_ALL = False
CORS_ORIGIN_WHITELIST = [
"http://frontend.example.com",
]
这样就可以控制哪些域名可以访问API了。
上线部署经验分享
1. 数据库选择:别再用 SQLite
开发阶段用 SQLite 完全没问题,但在生产环境一定要换成 PostgreSQL 或 MySQL,否则你将会面对并发写入失败、锁表、性能低下等各种问题。
我们项目最终选择了 PostgreSQL,并配合 Django 的内置 ORM 很好地完成了任务。
配置数据库只需修改 settings.py:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'mydb',
'USER': 'myuser',
'PASSWORD': 'mypassword',
'HOST': 'db-hostname',
'PORT': '5432',
}
}
另外,线上环境务必关闭 DEBUG = False,否则会有安全隐患!
2. 部署方式建议:Gunicorn + Nginx + Supervisor
Django自带的runserver只适合开发环境,生产环境我们一般用 Gunicorn 处理 WSGI 请求,配合 Nginx 反向代理实现高性能 Web 服务。
简单流程:
安装 Gunicorn:
pip install gunicorn编写 WSGI 应用入口(一般已由Django帮你生成)
启动 Gunicorn:
gunicorn --bind 0.0.0.0:8000 cms_project.wsgi配置 Nginx 作为反向代理(示例):
server { listen 80; location / { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } location /static/ { alias /path/to/static/; } location /media/ { alias /path/to/media/; } }使用 Supervisor 管理进程,防止服务崩溃或重启机器后自动恢复。
Supervisor配置示例:
[program:cms_project]
command = /path/to/venv/bin/gunicorn --workers 3 cms_project.wsgi
directory = /path/to/cms_project
autostart=true
autorestart=true
stderr_logfile=/var/log/cms_project.err.log
stdout_logfile=/var/log/cms_project.out.log
一些小技巧 & 经验分享
技巧一:充分利用 Admin
Django Admin 是非常强大的工具。对于中小型后台系统来说,几乎能满足所有CRUD需求。可以通过继承 ModelAdmin 并重写各种方法来自定义展示和行为。
例如:
- 列表页添加筛选器
- 自定义保存逻辑
- 增加额外动作(批量删除、导出CSV)
- 控制字段权限(某些字段只能特定角色编辑)
技巧二:合理使用缓存
对于频繁读取的数据(如文章详情页、统计数据),我们采用了 cache_page 装饰器进行局部缓存,有效减少数据库压力。
from django.utils.decorators import method_decorator
from django.views.decorators.cache import cache_page
@method_decorator(cache_page(60 * 5), name='dispatch')
class ArticleDetailView(DetailView):
...
这样可以让同一个文章在5分钟内重复访问时直接从内存缓存返回,而不是再去查一次数据库。
技巧三:日志记录 & 异常上报
我们集成了 Sentry 监控整个Django服务的异常情况,并开启了详细的日志输出,包括SQL语句(只用于调试)、请求参数、错误堆栈等。
配置示例(settings.py):
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'class': 'logging.StreamHandler',
},
},
'root': {
'handlers': ['console'],
'level': 'INFO',
},
}

生产环境建议将日志输出到文件或集中日志平台(如 ELK Stack)。
最终效果和收益
项目上线后,整个运营团队都反馈说使用体验不错,比之前用Excel手动更新内容高效太多了。
技术层面的收益也很明显:
- 两周内完成原型并上线
- 支持后续接口调用扩展
- 易于维护和二次开发
- 成为后续其他内部系统的基础模板
更重要的是,通过这次实践让我对Django在快速开发和生产环境部署方面的能力有了更深的认识。
总结:给想入门Django的同学的建议
如果你刚接触Django,建议从一个小项目开始练手,比如博客、任务管理系统、简易CMS等。
以下是我的几点建议:
- 先理解MTV架构思想:Django本质是MTV模式,掌握好Template、View、Model的关系是关键。
- 多看官方文档:Django的官方文档是最好的学习资源,语言清晰、结构完整、例子丰富。
- 善用第三方插件:比如DRF、django-taggit、django-cors-headers等都能极大提升开发效率。
- 注意安全配置:上线前必须关闭DEBUG、设置合适权限、加密敏感数据、防止XSS攻击。
- 性能从第一天就要考虑:虽然Django默认够用,但在高并发下需要优化查询、合理使用缓存。
- 保持代码简洁和模块化:每个app尽量单一职责,避免后期难以维护。
Django不是万能的,但它是一个非常适合初学者和中小项目的技术栈。尤其是在需要兼顾开发效率和稳定性的场景下,它的优势非常明显。
希望这篇真实案例分享能帮到正在学习Django的你,也希望你能用Django做出属于自己的第一个网站!
文章作者:老杨,某互联网公司后端开发工程师。喜欢折腾开源项目,热爱写作和分享。GitHub @xiaoyang-dev,欢迎交流。

评论 0