用Django搭建第一个Python网站:我的实战经验分享

黄庆林
2025-06-14 02:20
阅读 695

背景与起因

背景与起因

大家好,我是后端开发工程师小李。入行五年多,从最初的PHP到后来转向Python,再到现在的Go、Node混搭,技术一直在变,但Django始终是我在Python生态中最信赖的Web框架之一

今天想和大家分享下当初我第一次使用 Django 搭建一个完整网站的过程。虽然已经过去好几年了,但那种“从零开始写出一个能跑的服务”的成就感,至今仍记忆犹新。

当时我们公司接到一个客户的需求,要做一个用于内部资料上传管理的系统。客户对响应速度要求不高,但是希望快速上线,并且团队里有 Python 背景的人。于是,我们决定采用 Django 快速搭建原型。

这篇文章不是那种“hello world级别”的教程,而是基于实际项目的体验来写的,中间踩了不少坑,也总结出了不少经验,希望能给刚入门 Django 的同学一些帮助。


项目背景:为什么选择Django?

项目背景:为什么选择Django?

我们的项目是一个企业内部文档管理系统,主要功能包括:

  • 用户注册登录
  • 文档上传(支持PDF、Word)
  • 文档分类与标签管理
  • 权限控制(不同部门只能查看特定分类文档)

客户需求明确,时间又紧(两个月内要上线),我们团队都是Python出身。这时候 Django 的“电池已包含”特性就显得特别合适:

  • 自带admin后台,可以快速进行数据管理
  • ORM强大,写数据库逻辑方便
  • 用户认证机制成熟
  • 社区插件丰富,遇到问题容易找到解决方案

所以最终我们选用了 Django + PostgreSQL + Vue.js 做前后端分离架构。


问题一:从创建项目开始,第一步就卡住了?

问题一:从创建项目开始,第一步就卡住了?

还记得刚开始那会儿,执行 django-admin startproject mysite 创建完项目目录后,看着满眼的 .py 文件有点懵圈:

mysite/
    manage.py
    mysite/
        __init__.py
        settings.py
        urls.py
        asgi.py
        wsgi.py

这些文件到底是干嘛的?settings怎么配置?数据库还没连上怎么办?

解决方案1:先搞清楚项目结构

我花了一个下午把官方文档翻了一遍,结合 Google 上查到的文章,大致明白了这几个核心文件的作用:

  • manage.py:命令行工具,运行服务器、迁移数据库等操作都靠它。
  • settings.py:全局配置文件,数据库连接信息、第三方应用、静态资源路径都放这里。
  • urls.py:URL路由映射,类似前端路由的概念。
  • wsgi.py & asgi.py:部署时需要用到,一般初期可以不用管。

为了快速起步,我直接修改了 settings.py 中的数据库部分:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'doc_system',
        'USER': 'postgres',
        'PASSWORD': 'yourpassword',
        'HOST': 'localhost',
        'PORT': '5432',
    }
}

然后执行 python manage.py migrate 初始化数据库表,看到一堆默认的 auth 表生成,才松了一口气。

小贴士:建议初学者先使用 SQLite 开发,减少配置成本。后期再切换回 Postgres。


问题二:用户系统怎么做?

问题二:用户系统怎么做?

这个系统的用户权限设计其实不简单,因为涉及部门、角色(比如管理员、普通员工)、以及文档访问控制。如果完全自己实现,工作量不小。

解决方案2:利用Django内置auth模块

Django自带一套完整的用户系统,包括User模型、权限组、令牌等功能。我们可以:

  1. 使用默认的 User 模型
  2. 创建新的 Profile 模型扩展字段(如所属部门)
  3. 利用Group和Permission做权限管理

举个例子,我想给每个用户添加一个“部门”字段:

# models.py
from django.contrib.auth.models import User
from django.db import models

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    department = models.CharField(max_length=100)

# views.py
def user_profile(request):
    profile = request.user.profile
    return render(request, 'profile.html', {'profile': profile})

当然还要记得在 apps.py 里面注册 app,在 admin.py 注册模型才能在后台管理。

小插曲:有一次我误删了admin账户,整个后台进不去了。还好PostgreSQL中还有记录,手动加回来才发现原来密码是加密存储的。这让我意识到:一定要保护好你的超级用户账号,生产环境更要谨慎管理权限!


问题三:文档上传功能如何实现?

这是整个项目的核心功能之一,需要处理 PDF、Word 文件上传、存储、展示、下载。一开始我以为随便找个Form组件就搞定了,结果发现远远没那么简单。

解决方案3:自定义Model + File Upload 处理

1. 定义文档模型

# models.py
class Document(models.Model):
    title = models.CharField(max_length=255)
    file = models.FileField(upload_to='documents/%Y/%m/%d/')
    category = models.ForeignKey('Category', on_delete=models.SET_NULL, null=True)
    uploaded_by = models.ForeignKey(User, on_delete=models.CASCADE)
    tags = models.ManyToManyField('Tag')
    created_at = models.DateTimeField(auto_now_add=True)

这里的 upload_to 是指定媒体文件上传路径格式,按年月日分层级,避免单目录文件太多。

2. 设置MEDIA_ROOT和MEDIA_URL

在 settings.py 中添加:

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

同时在 urls.py 中加入:

from django.conf import settings
from django.conf.urls.static import static

urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

这样就能通过 /media/xxx.pdf 直接访问上传的文件了。

3. 上传接口设计

我采用了前后端分离的设计思路,前端用Vue.js传文件,后端提供 REST 接口接收并保存:

# views.py
from rest_framework.parsers import MultiPartParser, FormParser
from rest_framework.response import Response
from rest_framework.views import APIView

class UploadDocument(APIView):
    parser_classes = [MultiPartParser, FormParser]

    def post(self, request, *args, **kwargs):
        file_serializer = DocumentSerializer(data=request.data)
        if file_serializer.is_valid():
            file_serializer.save()
            return Response(file_serializer.data, status=status.HTTP_201_CREATED)
        else:
            return Response(file_serializer.errors, status=status.HTTP_400_BAD_REQUEST)

4. 遇到的问题及解决

  • 文件太大怎么办?

    我们最初测试阶段上传几十MB没问题,结果客户真的传了几百MB的视频!直接超时崩溃。

    最终方案:

    • 前端用axios设置timeout
    • 后端增加Nginx代理限制上传大小(通过client_max_body_size)
    • 引入断点续传(虽然最后没上线,但做了技术准备)
  • 安全性问题

    我们不允许任意类型的文件上传,尤其是 .php, .exe 等。所以在上传前加了一层白名单过滤:

    def validate_file_extension(value):
        ext = os.path.splitext(value.name)[1]
        valid_extensions = ['.pdf', '.docx', '.xlsx']
        if not ext.lower() in valid_extensions:
            raise ValidationError('Unsupported file extension.')
    

    在 Model 的 file 字段加上 validators 参数即可。


问题四:性能瓶颈出现——数据库慢得像蜗牛?

上线几个月后,文档数量涨到几万条,首页加载明显变慢。有时候用户刷新页面都要两三秒。

解决方案4:优化数据库查询 + Redis缓存

1. 查询优化:减少N+1查询问题

我们原本在首页显示文档列表的时候,每个文档都要查它的category名称、tags名称。这就导致了一个页面生成需要十几二十次SQL请求。

解决办法是使用 select_relatedprefetch_related

Document.objects.select_related('category').prefetch_related('tags')

这可以让Django一次把关联的数据全部拉取过来,大大减少查询次数。

2. 加Redis缓存

我们为文档详情页和首页引入了缓存机制:

from django.core.cache import cache

def get_document_detail(doc_id):
    key = f'document_{doc_id}'
    doc = cache.get(key)
    if not doc:
        doc = Document.objects.get(id=doc_id)
        cache.set(key, doc, timeout=60*15)  # 缓存15分钟
    return doc

缓存让整体响应时间下降到了200ms以内,效果立竿见影。

数据流转过程-2

3. 分页优化

当文档列表超过一万条后,翻页变得非常慢。我们启用了游标分页:

Paginator(Document.objects.all(), per_page=20)

或者更高级的,用DRF(Django REST Framework)提供的 CursorPagination,避免 offset 导致的性能下降。


问题五:生产环境怎么部署?

最开始我们用 runserver 本地跑着玩没问题,真要部署到生产服务器上才发现根本不行。我们需要考虑:

  • 如何部署?
  • 怎么处理静态文件?
  • 怎么保证高可用?
  • 错误日志去哪看?

解决方案5:Nginx + Gunicorn + Supervisor + Docker

我们最终采用的是:

Client -> Nginx -> Gunicorn -> Django App

同时引入 Supervisor 管理进程,Docker打包镜像。

静态文件管理

Django本身不适合处理静态资源,我们在 production settings 里改成了:

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')

# 收集所有静态文件到STATIC_ROOT
python manage.py collectstatic

Nginx中配置静态目录指向该路径:

location /static/ {
    alias /path/to/staticfiles/;
}

日志监控

我们还接入了 Sentry(错误追踪)和 ELK(日志收集),便于定位线上问题。


总结:Django的魅力在于“快”、“稳”、“全”

负载均衡配置-1

现在回头看,这个项目算是我们团队转型的第一个正式交付产品。Django确实帮我们节省了大量时间成本,尤其是在前期验证想法、快速迭代方面,展现出了极强的优势。

而且到现在为止,服务稳定运行一年多,没有出过大事故。这也验证了 Django 在中小型项目中的稳定性。


给新手的一些建议

如果你也是刚刚接触 Django,或者准备用它来开发自己的项目,以下是几点我亲身经历过的心得:

✅ 先从简单的项目练手

不要一开始就想着做一个大型平台。你可以先做个博客系统、投票网站,练练 Model、View、Template 的基本功。

✅ 把数据库设计清楚

ORM 再强大,也不能忽视数据库设计。合理的索引、外键关系、范式设计会让你受益终身。

✅ 多使用中间件和服务

像 DRF、Django-REST-Framework、Celery、Channels 这些工具都可以极大提升效率。别重复造轮子。

✅ 部署之前就开始考虑运维

很多人开发完成后才开始研究部署,结果各种报错。应该从开发初期就了解 WSGI、Gunicorn、NGINX 的基础原理。

✅ 多参与社区,少走弯路

Stack Overflow、GitHub Issues、Reddit 和知乎等社区都有很多真实案例可以参考。


结语:Django依然是Python Web开发的首选之一

随着FastAPI的兴起,不少人开始质疑Django是否过时了。但在我看来,Django依然适合中大型业务场景下的快速开发,尤其在复杂度较高、需要完整生态支持的项目中,它依然不可替代。

当然,Django也不是万能的。对于高并发、低延迟的微服务,我们也有其他的选择(如Go、Node、FastAPI)。但如果你正准备做一个传统意义上的Web系统,Django依然值得你深入学习。

希望这篇文章对你有所帮助,也欢迎留言交流你的使用经验!


作者简介:
小李,拥有5年后端开发经验,专注于Python生态,曾主导多个从0到1的Web系统项目落地。目前致力于构建高效稳定的后端架构体系。

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝