Django入门教程:搭建你的第一个Python网站

云端造物者
2025-12-16 01:59
阅读 882

县城的初夏,窗外蝉鸣吵得人脑壳疼。我坐在老家的书桌前,戴着降噪耳机放着《孤勇者》——别笑,代码写累了听这个真提神——一边在 VS Code 里敲着 Python,一边盘算着要不要把简历更新一下。

我在这家远程办公的小公司干了三年多,说是“后端开发”,其实天天在 Java 的世界里打转:Spring Boot、MyBatis、Redis、Kafka……一套组合拳打下来,连做梦都在 debug。但最近公司项目趋于稳定,老板又开始画饼说要“拥抱多语言生态”,顺手丢给我一个任务:“你不是一直对性能优化感兴趣嘛?试试用 Python 搞个轻量级管理后台,看看能不能替代一部分老旧的 Java 服务。”

说实话,一开始我是拒绝的。毕竟 Java 虽然啰嗦,但稳啊!线上跑了一年半没崩过(除了那次产品经理半夜改需求导致 OOM)。但转念一想,现在招聘市场上,会 Python + Django 的岗位越来越多,尤其是中小厂和 SaaS 初创公司,Django 几乎成了标配。我刷 BOSS 直聘时发现,不少 JD 都写着“熟悉 Django 优先”,甚至有些面试题挑战直接让你现场写个 CRUD 接口。

行吧,那就学!反正县城生活成本低,房租一个月 600,晚上还能陪爸妈散步,时间有的是。


为什么选 Django?而不是 Flask 或 FastAPI?

我知道很多人会说:“现在都 2024 年了,谁还用 Django 啊?Flask 够轻,FastAPI 性能炸裂!”
这话没错,但对我这种“小镇做题家”来说,上手速度 > 架构优雅 > 性能极致。Django 自带 ORM、Admin、Auth、Migrations,开箱即用,不用自己拼轮子。上周五晚上加班到 11 点,我还被运维大哥吐槽:“你们 Java 项目部署文档写了 50 页,光环境变量就 30 个,能不能学学人家 Python 社区,一行 python manage.py runserver 就跑起来了?”

虽然有点扎心,但确实是事实。Django 的“约定优于配置”哲学,特别适合快速验证想法。而且它的 Admin 后台,简直是给懒人准备的神器——数据库建好,注册一下模型,一个功能完整的后台就出来了,连前端都不用写。

当然,我也知道 Django 在高并发场景下不如 FastAPI,但在我们这种日活几千的小系统里,先跑起来,再优化,才是务实之道。更何况,Django 3.0+ 已经原生支持 ASGI,配合 Gunicorn + Uvicorn,性能也完全够用。


动手:从零搭建一个“资源分享站”

为了模拟真实场景,我决定做一个极简的“技术资源分享平台”——用户可以上传学习资料(比如 PDF、视频链接),其他人可以点赞、评论。这玩意儿听着简单,但涉及用户认证、文件存储、API 设计、数据库关系,正好练手。

第一步:环境准备(别跳过,血泪教训)

# 创建虚拟环境(县城网速慢,pip install 经常 timeout)
python -m venv django-env
source django-env/bin/activate  # Linux/Mac
# django-env\Scripts\activate   # Windows

pip install django pillow  # pillow 用于处理图片缩略图

踩坑记录:第一次没装 pillow,上传图片时报错 The _imaging C module is not installed,当时真的想砸电脑。后来才知道 Django 的 ImageField 依赖它。

第二步:创建项目 & 应用

django-admin startproject resource_hub
cd resource_hub
python manage.py startapp resources

项目结构如下:

resource_hub/
├── manage.py
├── resource_hub/       # 项目配置
│   ├── settings.py
│   ├── urls.py
│   └── ...
└── resources/          # 我们的应用
    ├── models.py
    ├── views.py
    └── ...

第三步:设计数据库模型(重点!性能优化从这里开始)

既然是资源分享站,核心模型有三个:用户(User,用 Django 自带的)资源(Resource)评论(Comment)

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

class Resource(models.Model):
    title = models.CharField(max_length=200)
    description = models.TextField()
    file = models.FileField(upload_to='resources/')  # 文件存储路径
    url = models.URLField(blank=True)  # 如果是在线资源
    uploader = models.ForeignKey(User, on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)
    likes = models.ManyToManyField(User, related_name='liked_resources', blank=True)

    class Meta:
        indexes = [
            models.Index(fields=['created_at']),  # 按时间排序常用
            models.Index(fields=['uploader']),    # 用户主页查自己的资源
        ]
        ordering = ['-created_at']

class Comment(models.Model):
    resource = models.ForeignKey(Resource, on_delete=models.CASCADE, related_name='comments')
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    content = = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        indexes = [
            models.Index(fields=['resource', 'created_at']),  # 评论按资源+时间查
        ]

为什么加索引?
去年双11期间,我们 Java 项目因为没给 order_by 字段加索引,导致列表页查询超时,DB CPU 打满。运维差点把我挂墙上。从此我养成了“凡查询必索引”的习惯。

另外,likesManyToManyField 而不是单独建表,是因为 Django 会自动创建中间表,省事。但如果未来点赞量爆炸(比如百万级),可能要考虑用 Redis 缓存计数,避免 JOIN 太重。


第四步:配置静态文件 & 媒体文件(生产环境必看)

开发时,Django 可以直接 serve 静态文件,但生产环境绝对不能这么干

我在 settings.py 里做了区分:

# settings.py
import os
from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent.parent

# 开发环境
if DEBUG:
    MEDIA_URL = '/media/'
    MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
else:
    # 生产环境建议用云存储(比如阿里云 OSS)
    DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
    AWS_ACCESS_KEY_ID = os.getenv('AWS_ACCESS_KEY_ID')
    AWS_SECRET_ACCESS_KEY = os.getenv('AWS_SECRET_ACCESS_KEY')
    AWS_STORAGE_BUCKET_NAME = 'my-resource-hub'
    MEDIA_URL = f'https://{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com/'

县城程序员的无奈:家里宽带上传只有 20Mbps,测试文件上传时等得想哭。后来干脆用 MinIO 搭了个本地 S3 兼容服务,速度快多了。


第五步:写视图 & API(RESTful 风格)

为了方便前后端分离(虽然这次我用 Django Template 快速出页面),我还是按 RESTful 设计接口:

方法 路径 功能
GET /resources/ 获取资源列表
POST /resources/ 创建新资源
GET /resources/{id}/ 获取单个资源详情
POST /resources/{id}/like/ 点赞

关键代码:

# resources/views.py
from django.shortcuts import render, get_object_or_404
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.contrib.auth.decorators import login_required
import json

@login_required
def resource_list(request):
    if request.method == 'GET':
        resources = Resource.objects.prefetch_related('likes').all()
        data = [{
            'id': r.id,
            'title': r.title,
            'likes_count': r.likes.count(),
            'uploader': r.uploader.username,
        } for r in resources]
        return JsonResponse(data, safe=False)
    
    elif request.method == 'POST':
        data = json.loads(request.body)
        resource = Resource.objects.create(
            title=data['title'],
            description=data.get('description', ''),
            uploader=request.user,
            url=data.get('url', '')
        )
        return JsonResponse({'id': resource.id}, status=201)

@login_required
def like_resource(request, resource_id):
    resource = get_object_or_404(Resource, id=resource_id)
    if request.user in resource.likes.all():
        resource.likes.remove(request.user)
        liked = False
    else:
        resource.likes.add(request.user)
        liked = True
    return JsonResponse({'liked': liked, 'count': resource.likes.count()})

注意prefetch_related('likes') 是为了 N+1 查询问题。如果不加,每条资源都要查一次点赞用户,100 条资源就是 101 次 SQL!我们 Java 项目就吃过这亏,JPA 的 @OneToMany 默认不 fetch,结果列表页慢如蜗牛。


第六步:跑起来!(以及那些年踩过的坑)

python manage.py makemigrations
python manage.py migrate
python manage.py createsuperuser  # 创建管理员,后面进 Admin 用
python manage.py runserver

访问 http://127.0.0.1:8000/admin,用刚才创建的账号登录,就能看到自动生成的后台!添加几个资源试试,简直不要太爽。

但别高兴太早——当你把 DEBUG=False 并部署到 Nginx 时,各种 404、500 就来了
我总结了三条生产部署 checklist:

  1. 收集静态文件python manage.py collectstatic
  2. 配置 ALLOWED_HOSTS:必须加上你的域名或 IP,否则 500 错误
  3. 数据库连接池:用 dj-database-url + psycopg2,别用默认 SQLite

和 Java 对比:Django 的“快”与“痛”

作为一个 Java 老兵,我不得不说,Django 在开发效率上碾压 Spring Boot。同样一个 CRUD 功能:

维度 Java (Spring Boot) Django
代码量 Controller + Service + Mapper + Entity + DTO ≈ 200 行 models.py + views.py ≈ 50 行
启动速度 5~10 秒 < 1 秒
学习曲线 高(注解、AOP、事务传播) 低(约定大于配置)
生态工具 Maven/Gradle 依赖复杂 pip + virtualenv 简单直接
类型安全 强类型,编译期报错 动态类型,运行时报错

但 Django 也有痛点:

  • 异步支持弱:虽然 ASGI 可用,但 ORM 还是同步的,高并发 I/O 密集型场景不如 FastAPI
  • 调试体验一般:PyCharm 断点还行,但远不如 IDEA 对 Java 的深度集成
  • 大型项目结构混乱:没有像 Spring 那样清晰的分层规范,容易写出“面条代码”

写在最后:这和求职有什么关系?

其实我折腾这个小项目,不只是为了完成老板的任务。最近在准备跳槽,刷了不少面试题挑战,发现很多公司(尤其是 To B SaaS 公司)都在用 Django 做内部系统、数据平台、甚至核心业务。

比如某家做 HR SaaS 的公司,一面就让我现场写个“员工信息管理”接口,要求支持分页、搜索、导出 Excel。用 Django 的 Admin + 自定义 Action,半小时搞定。而如果用 Java,光配 MyBatis Plus + PageHelper 就得折腾半天。

更重要的是,掌握多语言思维,能让你在面试中脱颖而出。当面试官问“你怎么看待不同框架的选型?”时,你可以结合 Java 和 Python 的实战经验,说出:“对于快速迭代的 MVP 产品,Django 的开发效率无可替代;但对于高并发交易系统,Java 的稳定性更可靠。”——这种回答,比背八股文强多了。


此刻,窗外天色已暗,我妈在喊我吃晚饭。我把代码 push 到 GitHub,顺手在 README 里加了一句:

“一个县城程序员的 Django 初体验。代码很糙,但能跑。如果你也在小城市远程工作,欢迎 star 交流。”

或许,这就是我们这些“小镇做题家”的浪漫:不在大厂卷 P9,也能用代码改变自己的一亩三分地。

对了,项目地址:github.com/yourname/resource-hub(假装存在)
下次聊聊怎么用 Django + Celery 做异步任务,解决文件上传阻塞的问题。毕竟,性能优化,永无止境

—— 一个边听《孤勇者》边写代码的县城后端

评论 0

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