用Django搭建我的第一个Python网站:真实项目中的成长之路
开始的缘由

大概三年前,我刚刚从Java转行到Python后端开发的时候,一个前辈同事给我推荐了Django:“如果你想要快速搭出一个稳定又功能齐全的Web站点,Django是绕不开的工具。”那时候我只是把它当作另一个框架来学,直到参与了一个内部系统重构的小项目——我们团队需要为公司新成立的市场部搭建一套简单但可用的内容管理平台(CMS),用于产品资料展示与客户资源登记。这个项目最终让我完整走通了Django的入门流程,并真正体会到它在实际工作中的价值。
在这篇文章中,我想以一个“过来人”的视角,结合那个项目的具体过程,带你一步步走进Django的世界。我会详细讲讲我是怎么一步一步从零开始搭建起一个可运行、可扩展的基础站点,同时也会分享一些真实开发过程中遇到的坑和解决思路。
初识问题:从零构建一个CMS系统的需求


接到任务那会儿,整个项目只有一个需求文档,内容很精简:
“为市场部门搭建一套基于网页的产品宣传站,支持后台编辑文章、上传图片、展示数据图表,并对外暴露API供其他系统对接。”
听起来像是个不难做的活,但刚接触Django的我当时还是有点发怵的。毕竟之前只做过简单的Flask小应用,对ORM、Admin管理、数据库建模这些概念都还停留在书本理解阶段。而且这毕竟是给业务部门使用的系统,不能太随便,稳定性、权限控制都要考虑进去。
于是我就决定,先从最基础的搭建开始,一边学一边干。
搭建环境和初步结构

安装和创建项目
pip install django
django-admin startproject marketcms
cd marketcms
python manage.py runserver
执行完这些命令后,浏览器打开http://127.0.0.1:8000/就能看到熟悉的 Django 欢迎页面,说明项目骨架已经搭起来了。
接下来就是创建我们的第一个App。根据官方建议,每个模块应该独立出来作为app来管理。我按照功能规划创建了以下几个App:
articles:管理文章和内容展示gallery:处理图片上传和展示leads:负责客户信息收集表单与数据存储api:提供对外接口服务
使用命令:
python manage.py startapp articles
然后把每个App注册到settings.py的INSTALLED_APPS中。
数据库选择与初始配置
默认情况下,Django 使用的是 SQLite,适合本地开发测试。但在生产环境中显然不行。我们当时就考虑直接上 PostgreSQL,这样后续迁移和部署也更方便。
所以在settings.py中将数据库配置改成了PostgreSQL:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'marketcms_db',
'USER': 'dbuser',
'PASSWORD': 'secretpass',
'HOST': 'localhost',
'PORT': '5432',
}
}
顺带提一句,如果是多人协作项目,最好把.env文件引入进来保存敏感配置,避免把密码写死在代码里。这一点后来我们项目上线时吃了亏,后面会提到。
实战开发:从模型设计到功能实现

模型设计(Model)
首先从最核心的数据结构开始:文章模型。
# articles/models.py
from django.db import models
from django.contrib.auth.models import User
class Article(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
author = models.ForeignKey(User, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
这里有几个要点:
- 使用了
ForeignKey关联到Django内置的User模型,这样可以轻松实现权限控制 - 时间字段用
auto_now_add和auto_now自动填充时间戳 __str__方法是为了在Admin界面显示更友好
接着运行迁移命令生成数据库表:
python manage.py makemigrations
python manage.py migrate
遇到的第一个坑:数据库同步失败
我在一次提交修改后运行makemigrations没报错,但migrate时报错了:
django.db.utils.ProgrammingError: relation "articles_article" already exists
原来是之前手动执行过SQL或者重复执行过migration。这个时候要用--fake-initial来强制匹配状态:
python manage.py migrate --fake-initial
不过这也提醒我:一定要善用版本控制和记录迁移日志,否则容易出现混乱。
编写视图(View)与模板(Template)
接下来就是编写页面逻辑。一开始我使用了函数式视图(Function-based Views),因为更容易理解和调试。
比如展示所有文章的首页视图:
# articles/views.py
from django.shortcuts import render
from .models import Article
def index(request):
articles = Article.objects.all().order_by('-created_at')
return render(request, 'articles/index.html', {'articles': articles})
然后创建模板目录结构:
marketcms/
├── templates/
│ └── articles/
│ └── index.html
模板内容大致如下:
<!-- templates/articles/index.html -->
<!DOCTYPE html>
<html>
<head><title>文章列表</title></head>
<body>
<h1>欢迎来到文章列表页</h1>
{% for article in articles %}
<div>
<h2>{{ article.title }}</h2>
<p>{{ article.content|truncatewords:30 }}</p>
</div>
{% endfor %}
</body>
</html>
然后在urls.py中绑定路径:
# marketcms/urls.py
from django.urls import path
from articles import views
urlpatterns = [
path('', views.index),
]
这时候再访问http://127.0.0.1:8000/就能看到文章列表了!
Admin后台初体验
Django 最强大的功能之一就是它的 Admin 后台管理系统。只需要简单几步就能拥有一个完整的管理界面。
我们在admin.py中注册模型:
# articles/admin.py
from django.contrib import admin
from .models import Article
admin.site.register(Article)
然后创建管理员账号:
python manage.py createsuperuser
登录之后就能直接操作文章内容了,完全不需要自己写CRUD页面!
接口设计与REST API(DRF的集成)
市场部的另一项需求是开放部分数据给CRM系统调用,这就涉及到接口的设计。
我们选择了 Django REST framework(DRF) 来做这件事,因为它天然与Django生态兼容,开发效率很高。
安装DRF:
pip install djangorestframework
添加进配置:
# settings.py
INSTALLED_APPS += ['rest_framework']
然后创建一个ArticleSerializer:
# api/serializers.py
from rest_framework import serializers
from articles.models import Article
class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = ['id', 'title', 'content', 'author', 'created_at']
视图则使用基于类的通用APIView:
# api/views.py
from rest_framework.generics import ListAPIView
from articles.models import Article
from .serializers import ArticleSerializer
class ArticleListView(ListAPIView):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
URL绑定:
# api/urls.py
from django.urls import path
from .views import ArticleListView
urlpatterns = [
path('articles/', ArticleListView.as_view()),
]
最后接入主路由:
# marketcms/urls.py
from django.urls import include, path
urlpatterns += [
path('api/', include('api.urls')),
]
这样访问http://127.0.0.1:8000/api/articles/就能看到JSON格式的文章列表了!
真实踩坑经验分享
坑一:跨域请求问题(CORS)
DRF搭建好以后,前端尝试调用接口时遇到了经典的跨域错误:
Blocked by CORS policy: No 'Access-Control-Allow-Origin' header present on the requested resource.
解决方式很简单,安装并配置django-cors-headers即可:
pip install django-cors-headers
在settings.py中加入中间件并设置允许域名:
MIDDLEWARE = [
...
'corsheaders.middleware.CorsMiddleware',
...
]
CORS_ORIGIN_ALLOW_ALL = False
CORS_ORIGIN_WHITELIST = (
'http://localhost:3000',
)
别忘了加中间件顺序,否则可能拦截不到请求!
坑二:静态文件与媒体资源处理
当我们上线准备部署的时候,发现前端上传的图片无法正常显示,提示404 Not Found。
这是因为Django默认不处理静态资源(如CSS、JS)以及用户上传的媒体文件。解决方法分两步:
- 在开发环境下启用静态文件服务:
# settings.py
STATIC_URL = '/static/'
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或类似服务器处理静态资源,Django不建议自行托管。
坑三:数据库事务与性能优化
在一个页面中同时加载多个模型数据时,我发现了明显的卡顿。查了Log后发现执行了非常多条SQL语句。
例如:
# 错误写法:每循环一次执行一条查询
for comment in article.comments.all():
print(comment.author.username) # 这里触发了额外查询
解决方案当然是使用select_related()和prefetch_related()进行预加载优化。
正确的做法是:
# 正确写法:预先获取外键数据
Article.objects.select_related('author').all()
对于多对多关系,则使用prefetch_related,比如评论和点赞关系:
Article.objects.prefetch_related('comments__likes')
这样做能大大减少数据库请求数量,提高响应速度。
上线与部署心得
项目完成后,我们选择使用Gunicorn+Nginx的方式进行部署,配合PostgreSQL+Redis缓存。
几点上线后的经验:
- 使用
gunicorn marketcms.wsgi:application --bind 0.0.0.0:8000启动服务 - Nginx反向代理配置静态文件路径,提升性能
- 配合
whitenoise静态文件中间件简化前端资源管理 - 所有环境变量通过
.env统一管理,不暴露在settings.py中 - 定期检查数据库索引,必要时使用
explain analyze查看慢查询
效果总结与收获
整个项目历时一个月左右完成,从最初一头雾水到现在能够独立完成模块设计,最大的感触是:
“Django并不是万能的,但它确实让开发变得可控、高效。”
通过这次实战,我不仅掌握了Django的核心机制,还了解了如何从零开始搭建一个工程级项目。更重要的是,学会了在面对突发问题时,如何快速定位并找到解决方案。
这个项目最终交付给市场部后被广泛使用,甚至一度成为了公司内部知识库的基础架构之一。
给初学者的一些建议

✅ 快速起步的几个建议:
- 别怕动手:Django本身自带很多开箱即用的功能,不要只看书不动手写代码。
- 学会看文档:遇到问题优先翻阅官方文档,很多时候答案都在里面。
- 善用社区资源:Stack Overflow、知乎、掘金等都有丰富的案例,能帮你省去不少试错时间。
- 从真实需求入手:哪怕是一个小功能,也要模拟真实场景去做。
❗避坑指南
- 不要把所有代码都放在
views.py里,拆分成services、utils、models更清晰 - 别忘记写单元测试,Django提供了很好用的
TestCase框架 - 不要硬编码敏感信息,用环境变量或配置中心管理
- 生产环境不要用
runserver,而是用正式部署方案
📌 结尾的一些感悟
回想当初第一次跑起来Django项目时激动的心情,再对比现在能从容应对各种问题的状态,真的感慨良多。希望这篇文章对你学习Django能有所帮助,也希望你能在这个框架中找到属于自己的乐趣。
如果你在学习Django的过程中遇到了什么具体问题,欢迎留言交流。一起在编程的路上越走越远吧!
本文为作者亲身经历撰写,未经许可禁止转载,违者必究。

评论 0