从零开始,用Django搭建我的第一个Python网站

产品别催我
2025-06-18 15:07
阅读 245

起因:为什么选择Django?

起因:为什么选择Django?

说实话,最开始写网站的时候我也是个门外汉。当时公司要做一个内部管理平台,用来追踪我们项目进度和人员分配。时间紧、任务重,技术选型上希望快速上线且能稳定运行,还要方便后期扩展。

之前我接触过Node.js和Flask,但都不是特别适合这种“小团队、快节奏”的场景。后来一位前辈推荐了Django——他笑着说:“你要是想省事儿,就用它吧,开箱即用的东西多得是。”

于是,抱着试试看的心态,我开始了与Django的第一次正式合作。


第一次接触:从安装到Hello World

第一次接触:从安装到Hello World

还记得第一天装环境的时候,各种包冲突让我差点放弃。那会儿我对Python虚拟环境都还懵懵懂懂,pip和venv之间的关系也没搞清楚。

不过,一旦把基础环境搭好之后,Django真的挺顺手。比如创建工程:

django-admin startproject mysite
cd mysite
python manage.py runserver

打开浏览器访问 http://127.0.0.1:8000,那一刻看到熟悉的“It worked!”页面时,心里是真的踏实下来了。

然后就是创建应用(App),在Django里每个功能模块都是一个App:

python manage.py startapp projecttracker

接着我在 views.py 中写了一个简单的视图函数:

from django.http import HttpResponse

def index(request):
    return HttpResponse("欢迎来到我们的项目管理后台!")

并在 urls.py 中配置路径映射:

from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name='index'),
]

这算是完成了第一个真正的功能模块入口。虽然简单,但整个流程跑通了之后,我对后续的工作也更有信心了。


遇到的第一个大挑战:数据库设计

遇到的第一个大挑战:数据库设计

随着需求逐渐清晰,我开始设计模型(Models)。最初的想法很简单:记录项目信息、成员信息以及任务分配。

于是我写了如下几个Model类:

from django.db import models

class Project(models.Model):
    name = models.CharField(max_length=100)
    description = models.TextField(blank=True, null=True)
    start_date = models.DateField()
    end_date = models.DateField()

    def __str__(self):
        return self.name

class Member(models.Model):
    name = models.CharField(max_length=50)
    role = models.CharField(max_length=30)

    def __str__(self):
        return self.name

class Task(models.Model):
    project = models.ForeignKey(Project, on_delete=models.CASCADE)
    member = models.ForeignKey(Member, on_delete=models.SET_NULL, null=True)
    title = models.CharField(max_length=200)
    status = models.CharField(max_length=20, choices=[
        ('pending', '待处理'),
        ('in_progress', '进行中'),
        ('completed', '已完成')
    ])
    due_date = models.DateField()

    def __str__(self):
        return self.title

看起来没毛病,对吧?但实际上问题很快就暴露出来了。

数据库表关系混乱

起初我觉得每个对象之间通过外键关联就能搞定。但在实际使用中,当项目数量变多、成员频繁变动后,一些历史数据就开始出现异常。比如某个成员离职后删除记录,导致对应的历史任务变成了无效引用。

这时候我才意识到,外键的级联策略必须谨慎选择。比如我改成了将 on_delete=models.SET_NULL,并确保相关字段允许为空,避免数据断裂。

另外还有一个更深层次的问题:系统中存在很多状态性的信息,这些是否应该固化成快照,而不是实时引用?

这个问题我在后面做报表统计时才彻底意识到。后来我们引入了“ProjectSnapshot”这样的结构来存储项目关键状态的历史记录,避免因为原始数据变更而导致报表失真。

经验总结:Model设计要提前规划好生命周期和变更逻辑

  • 外键字段尽量不要直接删除依赖对象,可以考虑 SET_NULL 或者软删除方案。
  • 涉及历史状态的字段,建议保存当时的值或引入快照机制。
  • 如果未来可能做数据分析,某些字段的设计要考虑可追溯性。

接口设计:前后端分离还是模板驱动?

早期我其实是打算用Django默认的模板渲染方式来做的,毕竟开发效率高嘛。但随着前端同学接入后,我们决定改为前后端分离架构。

这里其实有个转折点:前端需要用Vue来做组件化开发,而Django作为API服务提供JSON数据,这样协作起来也更清晰。

为此,我引入了 Django REST framework(DRF) 来构建REST API。

比如,获取项目列表的接口实现如下:

# serializers.py
from rest_framework import serializers
from .models import Project

class ProjectSerializer(serializers.ModelSerializer):
    class Meta:
        model = Project
        fields = '__all__'

# views.py
from rest_framework.generics import ListAPIView
from .models import Project
from .serializers import ProjectSerializer

class ProjectListView(ListAPIView):
    queryset = Project.objects.all()
    serializer_class = ProjectSerializer

# urls.py
from django.urls import path
from .views import ProjectListView

urlpatterns = [
    path('projects/', ProjectListView.as_view(), name='project-list'),
]

这个过程中我也踩了不少坑,比如CSRF保护带来的跨域问题、请求头未正确设置导致403报错等。最后通过配置 CORS 插件解决了前端访问的问题。

此外,考虑到权限控制的需求,我们也做了基本的身份验证机制。比如只允许登录用户访问特定接口:

from rest_framework.permissions import IsAuthenticated

class ProjectListView(ListAPIView):
    permission_classes = [IsAuthenticated]
    ...

这部分内容也让我更加深入理解了Django的认证体系,以及如何灵活扩展中间件和权限策略。


真正上线前遇到的那些坑

部署到生产环境并不是一件轻松的事。一开始我们在测试环境中用的是SQLite,结果上线后发现根本撑不住并发量。性能瓶颈很快显现出来。

数据库换成了PostgreSQL

这是第一次真正意义上做数据库迁移。好在Django的ORM抽象程度很高,大部分模型代码不需要修改。只需要改一下 settings.py 的DATABASE配置:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'mydb',
        'USER': 'myuser',
        'PASSWORD': 'mypassword',
        'HOST': 'localhost',
        'PORT': '',
    }
}

但也不是一点麻烦都没有。有些开发环境中自动生成的SQL语句,在PostgreSQL下执行失败了。比如字段名用了关键字或者大小写不一致,都需要手动修正。

所以在这里给新手提个醒:如果你的目标是部署到PostgreSQL,一开始就别用SQLite开发!

性能优化:静态文件、缓存和Nginx配置

我们用上了Gunicorn + Nginx的方式来部署。刚开始没注意静态文件路径的问题,前端加载CSS、JS总是出错。

解决办法是在 settings.py 中添加:

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

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

然后运行:

python manage.py collectstatic --noinput

同时配合Nginx代理静态文件路径:

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

location /media/ {
    alias /path/to/media/;
}

location / {
    proxy_pass http://127.0.0.1:8000;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

关于缓存方面,我们后来加了Redis做视图缓存和Session存储。这部分配置在 CACHESSESSION_ENGINE 中都可以找到对应的参数。

不过要注意的一点是:不同环境下Redis连接池和超时时间的设置要根据服务器性能调整,不然可能会出现“连接等待超时”等问题。


上线后的效果:从开发到运维的转变

项目上线后反馈还不错。前端界面响应流畅,后端接口稳定性也可以接受。不过上线不是终点,而是新的起点。

我们开始着手优化日志采集、错误监控和自动化部署的事情。比如引入 Sentry 做异常追踪,用 GitLab CI 实现自动化测试和发布流程。

运维层面也开始定期检查数据库索引情况、慢查询日志、连接数限制等。

这段时间让我明白一个道理:一个完整的Web项目不仅仅是写完功能就完事了,运维、监控、日志、安全这些都是不能忽视的部分。


我想分享的一些经验和建议

1. 框架只是工具,理解本质更重要

Django确实帮你封装了很多东西,但作为一个开发者,你要知道它背后是怎么运作的。比如中间件、ORM、Template引擎,这些东西的底层原理搞清楚,才能写出更高效的代码。

2. 数据库设计是项目的基石

尤其对于管理系统类产品来说,数据模型一旦定下来,后面修改的成本极高。初期花些时间画ER图、做字段命名规范,比后期返工划算得多。

3. 学会善用社区资源

Django生态非常丰富,有无数优秀的第三方库可以直接用。像DRF、Django-Filter、Django-CORS-Headers 这些都是我日常工作中离不开的好帮手。合理利用开源力量,能节省大量重复造轮子的时间。

4. 别怕踩坑,多记录,多复盘

每次遇到一个问题,我都习惯记录下来,包括问题现象、排查过程、解决方案。久而久之你会发现,很多问题都有相通之处。积累越多,解决问题的速度就越快。

5. 重视文档和注释

这一点往往容易被忽略。尤其是多人协作的项目中,良好的注释和文档不仅能帮助新人快速上手,也能让未来的自己少走弯路。


写在结尾:技术成长永远在路上

现在回头看看当初那个用Django搭起第一个网站的我,已经可以从容地设计API、优化数据库、甚至重构架构了。这段经历不仅让我掌握了Django的使用方法,更让我明白了作为开发者应有的工程思维和系统观。

如果你是刚入门的新手,别怕犯错,Django是一个非常适合练手的框架;如果你是有一定经验的开发者,也完全可以借助它快速落地想法、验证产品方向。

希望这篇文章能成为你学习Django道路上的一盏小灯。愿你在编程的世界里越走越远,写出更优雅、稳定的Web应用。


附录:文中提到的核心目录结构示例

mysite/
├── manage.py
├── mysite/
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── projecttracker/
│   ├── migrations/
│   ├── models.py
│   ├── views.py
│   ├── serializers.py
│   └── urls.py
├── staticfiles/
└── media/

如需完整源码,可私信我获取GitHub仓库地址。我们会在那里持续更新实战项目案例,期待你的加入!


评论 0

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