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

清醒开发者
2025-12-19 02:24
阅读 1966

上周五晚上九点半,我坐在公司工位上,盯着屏幕上那个因为缓存没刷新而疯狂报错的接口,心里默默问候了产品经理全家。这已经是本周第三次临时改需求了——“小张啊,我们能不能加个用户注册页面?很简单,就一个表单。”
简单?呵。

我是小张,坐标上海,租住在公司旁边的老小区(月租四千五还天天漏水)。在一家不到三十人的小厂做后端开发,一个人负责整个业务线——从数据库设计、API开发到部署上线,连半夜报警都归我管。最近公司想搞点AI功能,领导看我在GitHub上点过几个PyTorch的star,直接甩来一句:“你不是学Python的吗?顺便把官网也搭一下。”

行吧。反正我本来也在偷偷准备求职简历,想着多堆点项目经验。正好,用 Django 搭个网站,既能练手,又能写进简历里——“独立完成高可用Web系统架构设计”(虽然实际上就是个静态页+注册表单 😅)。


为什么是 Django?

我知道很多人会说:“现在都2024年了,谁还用Django?FastAPI不香吗?”
但兄弟,现实很骨感。小厂资源有限,没人帮你写CI/CD脚本,运维大哥只会 systemctl restart nginx,测试小姐姐连Postman都不会用。这时候,Django 的“开箱即用”简直就是救命稻草。

  • 自带Admin后台(老板看了直呼专业)
  • ORM 能让你少写80%的SQL(避免我这种SQL手残党写出 DELETE FROM users; 这种史诗级事故)
  • 内置用户认证、CSRF防护、模板系统……省得自己造轮子
  • 社区成熟,Stack Overflow 上一搜一大把答案

而且,Python 本身生态太强了——今天写网站,明天接个爬虫任务,后天还能跑个AI模型推理。一套语言打天下,跳槽时简历也能写得花里胡哨:“全栈能力 + AI工程化经验”。


动手!从零开始搭站

第一步:环境初始化(别跳过虚拟环境!)

我见过太多新人直接 pip install django 全局安装,结果后来装个 scrapy 把依赖搞崩,哭着删库重装。记住,在 Python 世界,虚拟环境是底线

# 创建项目目录
mkdir mysite && cd mysite

# 创建虚拟环境(推荐用 venv,不用 conda,小厂服务器没装anaconda)
python -m venv venv

# 激活(Linux/Mac)
source venv/bin/activate
# Windows 用 venv\Scripts\activate

# 安装 Django
pip install django

💡 血泪教训:去年双11前,我图快没建虚拟环境,结果线上服务器同时跑了 Flask 和 Django 项目,两个版本的 requests 库打架,半夜三点被钉钉叫醒。从此立誓:无虚拟环境,不编码。

第二步:创建项目 & App

Django 的“项目 vs App”概念一开始容易懵。简单理解:

  • Project = 整个网站(比如 yourcompany.com)
  • App = 网站里的一个模块(比如 blog / user / api)
django-admin startproject mysite .
python manage.py startapp accounts

然后在 mysite/settings.py 里注册你的 App:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    # ... 其他默认项
    'accounts',  # ← 加上这行
]

第三步:设计用户模型(性能第一!)

小厂没DBA,数据库设计全靠自觉。别一上来就 TextField 堆满,要考虑索引、查询效率、未来扩展。

我想做个简单的用户注册,只存邮箱和密码(当然密码要加密!)。Django 自带 AbstractUser,直接继承就行:

# accounts/models.py
from django.contrib.auth.models import AbstractUser
from django.db import models

class CustomUser(AbstractUser):
    email = models.EmailField(unique=True)
    created_at = models.DateTimeField(auto_now_add=True)

    USERNAME_FIELD = 'email'  # 用邮箱登录
    REQUIRED_FIELDS = ['username']  # 保留用户名字段(Django admin 需要)

然后修改 settings.py 指向自定义用户模型:

AUTH_USER_MODEL = 'accounts.CustomUser'

⚠️ 注意:这个配置必须在第一次 migrate 前设置好! 否则后面改会炸库。我上次手滑忘了,结果 makemigrations 出现 You are trying to change the AUTH_USER_MODEL... 直接心态崩了。

执行迁移:

python manage.py makemigrations
python manage.py migrate

第四步:写个注册视图(别裸奔!)

很多教程直接 views.py 里写函数返回 HTML,但生产环境要考虑:

  • 表单验证
  • 密码强度
  • 防暴力注册(限流)
  • CSRF 防护

我用 Django 内置的 CreateView + UserCreationForm 改造:

# accounts/forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from .models import CustomUser

class CustomUserCreationForm(UserCreationForm):
    class Meta:
        model = CustomUser
        fields = ('email', 'password1', 'password2')
# accounts/views.py
from django.urls import reverse_lazy
from django.views.generic import CreateView
from .forms import CustomUserCreationForm

class SignUpView(CreateView):
    form_class = CustomUserCreationForm
    success_url = reverse_lazy('login')
    template_name = 'registration/signup.html'

模板文件 accounts/templates/registration/signup.html 就略了,反正前端不是我的强项(CSS 写得像90年代网页),但至少用了 Django 的 {% csrf_token %},安全底线守住。


性能优化:小厂也要有追求

别以为小项目就不用考虑性能。上周刚因为一个没加索引的查询,导致注册接口响应时间从 200ms 飙到 2s,测试直接提了 P0 级 Bug。

1. 数据库索引

检查你的查询是否走了索引:

# 开启 SQL 日志
python manage.py shell
>>> from django.conf import settings
>>> settings.DEBUG = True
>>> from accounts.models import CustomUser
>>> list(CustomUser.objects.filter(email='test@example.com'))
>>> from django.db import connection
>>> print(connection.queries[-1]['sql'])

如果看到 Seq Scan(顺序扫描),赶紧加索引:

# models.py
class CustomUser(AbstractUser):
    email = models.EmailField(unique=True, db_index=True)  # unique 已隐式建索引,但显式写更清晰

2. 缓存策略

用户注册虽然写操作多,但后续的登录、个人信息读取可以缓存。Django 支持 Redis、Memcached:

# settings.py
CACHES = {
    'default': {
        'BACKEND': 'django_redis.cache.RedisCache',
        'LOCATION': 'redis://127.0.0.1:6379/1',
        'OPTIONS': {
            'CLIENT_CLASS': 'django_redis.client.DefaultClient',
        }
    }
}

然后在 view 里:

from django.core.cache import cache

def get_user_profile(request, user_id):
    profile = cache.get(f'user_profile_{user_id}')
    if not profile:
        profile = fetch_from_db(...)  # 你的数据库查询
        cache.set(f'user_profile_{user_id}', profile, timeout=300)  # 缓存5分钟
    return profile

3. Gunicorn + Nginx 部署(别用 runserver 上线!)

本地开发用 python manage.py runserver 没问题,但绝对不能用于生产!它单线程、无并发、内存泄漏风险高。

标准小厂部署方案:

# 安装 Gunicorn
pip install gunicorn

# 启动(4个工作进程)
gunicorn --workers 4 --bind 0.0.0.0:8000 mysite.wsgi:application

前面再套一层 Nginx 做静态文件托管和反向代理:

server {
    listen 80;
    server_name yourdomain.com;

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

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

📌 运维友好提示:记得让运维大哥把 ulimit -n 调高,否则高并发下 socket 文件描述符不够用,你会看到 OSError: [Errno 24] Too many open files —— 我们组去年就因此挂过一次。


和爬虫、AI 的联动(求职加分项!)

Django 不只是做网站。我在项目里顺手加了个 /api/scrape/ 接口,调用内部爬虫服务(用 Scrapy 写的),把抓到的数据存进数据库,前端展示趋势图。面试时一说“我用 Django 做了数据采集平台”,HR眼睛都亮了。

更骚的是,最近在学 LangChain,打算把用户注册后的欢迎邮件改成 AI 生成:“Hi 小张,欢迎加入!根据你的兴趣(来自爬虫抓取的公开信息),我们推荐你关注 XXX…” —— 虽然可能侵犯隐私,但求职简历上能写“AI驱动个性化推荐系统”,谁还在乎细节?


总结:代码人生,不止 CRUD

折腾完这个小站,我最大的感受是:技术选型要匹配团队规模。大厂可以微服务、K8s、Service Mesh,但我们这种小厂,Django 的“Batteries included”才是真·生产力工具。

而且,当你一个人扛起整条业务线,你会被迫思考:

  • 数据库怎么设计才不容易重构?
  • 接口要不要加限流?
  • 日志怎么打才能快速定位问题?
  • 怎么让运维愿意帮你重启服务?

这些经验,远比背八股文有用。上周面试一家中厂,面试官问我:“你们小厂怎么做性能监控?” 我直接掏出自己写的 Prometheus + Grafana 面板截图(用 Django middleware 收集 QPS 和延迟),当场拿到 offer。

所以,别小看一个“简单的 Django 网站”。它可能是你跳出 CRUD、走向代码人生的第一步。

最后附上我的项目结构(精简版):

mysite/
├── accounts/              # 用户模块
│   ├── models.py          # 自定义用户模型
│   ├── views.py           # 注册/登录视图
│   └── templates/         # HTML模板
├── mysite/
│   ├── settings.py        # 关键配置:缓存、数据库、安全
│   └── urls.py            # 路由分发
├── static/                # 静态文件(CSS/JS)
├── requirements.txt       # 依赖列表(务必冻结版本!)
└── manage.py

关键配置对比表:

配置项 开发环境 生产环境
DEBUG True False
ALLOWED_HOSTS ['*'] ['yourdomain.com']
数据库 SQLite PostgreSQL/MySQL
静态文件 runserver 托管 Nginx 托管
日志级别 DEBUG WARNING

搞定收工。现在这个网站已经跑在阿里云最低配 ECS 上(2核4G,月付98块),每天处理不到100个请求,稳如老狗。
下次产品经理再说“加个功能很简单”,我就把这篇教程甩他脸上——“来,你照着做一遍?”

(完)

作者:小张,上海某小厂后端,白天修 Bug,晚上学 AI,梦想是写出不被产品经理骂的代码。
GitHub:假装有个链接(其实私有仓库不敢开源)
求职状态:看机会中,欢迎内推 Python 后端 or AI工程岗!

评论 0

最热最新
暂无评论
清醒开发者Lv.1
0
影响力
0
文章
0
粉丝