Django入门教程:搭建你的第一个Python网站
上周五晚上九点半,我坐在公司工位上,盯着屏幕上那个因为缓存没刷新而疯狂报错的接口,心里默默问候了产品经理全家。这已经是本周第三次临时改需求了——“小张啊,我们能不能加个用户注册页面?很简单,就一个表单。”
简单?呵。
我是小张,坐标上海,租住在公司旁边的老小区(月租四千五还天天漏水)。在一家不到三十人的小厂做后端开发,一个人负责整个业务线——从数据库设计、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