Django入门教程:搭建你的第一个Python网站
上周五晚上十点半,我还在公司改一个医疗表单的校验逻辑。产品经理凌晨两点发来的微信消息还钉在聊天窗口顶部:“这个字段能不能加个实时提示?”——而我的 MacBook Pro 已经烫得能煎蛋了。
我是某医疗软件公司的 Python 开发,三年前从 Go 转过来写 Django,理由很朴素:公司主栈是 Python + Django,而我那会儿刚被“优化”出上一家搞云原生的小厂。虽然私下还是更爱 Go 的简洁和编译时安全感,但为了饭碗,Django 也慢慢成了我的主力武器。最近因为考虑跳槽(别问,问就是 PIP 面谈又没过),开始重新梳理基础,顺便把一些踩过的坑整理出来——于是就有了这篇面向新手的 Django 入门实战。
为什么不是 Flask?也不是 Go?
很多新人一上来就问:“为什么不直接用 Flask?轻量啊!” 或者 “Go 写 Web 不是更快吗?”
说实话,在我们这种医疗系统里,“快”从来不是第一优先级。稳定、可审计、有成熟生态支持才是命脉。Django 自带 admin、ORM、用户认证、CSRF 防护,这些在处理患者数据时简直是救命稻草。你敢信?去年双11期间我们系统崩了一次,根因居然是某个外包团队用裸 SQL 拼接参数导致注入漏洞——自那以后,老板勒令所有新项目必须用 Django ORM。
至于 Go,我确实怀念它那丝滑的并发模型和零依赖部署。但现实是:我们的前端同事只会 JavaScript,后端接口要是返回 protobuf 而不是 JSON,他们能当场罢工。而且,医疗行业对审计日志要求极高,Django 的信号(signals)机制配合 django-simple-history 插件,能自动记录每个字段的变更历史,Go 生态里要自己造轮子,成本太高。
所以,别纠结“最酷”的技术,先搞定“最稳”的方案。
动手!创建你的第一个 Django 站点
别被“网站”吓到。在 Django 里,一个“项目”(project)可以包含多个“应用”(app),比如 patient、billing、report。我们今天就建个极简的患者登记页。
# 假设你已装好 Python 3.9+ 和 pip
pip install django
django-admin startproject clinic_site
cd clinic_site
python manage.py startapp patients
然后在 clinic_site/settings.py 里注册这个 app:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
# ... 其他默认项
'patients', # ← 加这一行
]
接下来定义模型。医疗系统最怕数据不一致,所以我们用 Django ORM 强约束:
# patients/models.py
from django.db import models
class Patient(models.Model):
GENDER_CHOICES = [('M', 'Male'), ('F', 'Female'), ('O', 'Other')]
name = models.CharField(max_length=100)
id_number = models.CharField(max_length=18, unique=True) # 身份证号唯一
gender = models.CharField(max_length=1, choices=GENDER_CHOICES)
birth_date = models.DateField()
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
跑迁移:
python manage.py makemigrations
python manage.py migrate
这时候如果你像我一样习惯用 Mac 开发,终端里敲命令飞快;但别忘了,测试还得切 Windows 虚拟机——上周就因为 Windows 上路径大小写敏感问题,测试同事追着我骂了半小时。
别只写后端!前端交互也很香
我知道,很多后端兄弟看到前端就头大。但既然我对动画和交互感兴趣(业余时间甚至偷偷学了 GSAP),这次干脆把前端也包了。
我们在 patients/views.py 里写个简单视图:
from django.shortcuts import render
from .models import Patient
def patient_list(request):
patients = Patient.objects.all()
return render(request, 'patients/list.html', {'patients': patients})
然后配路由:
# clinic_site/urls.py
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('patients/', include('patients.urls')),
]
# patients/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.patient_list, name='patient_list'),
]
模板 patients/templates/patients/list.html 用点简单的 JavaScript 做加载动画:
<div id="loading" style="display:none;">加载中...</div>
<ul id="patient-list"></ul>
<script>
fetch('/api/patients/') // 假设有 API 接口
.then(res => {
document.getElementById('loading').style.display = 'block';
return res.json();
})
.then(data => {
const ul = document.getElementById('patient-list');
data.forEach(p => {
const li = document.createElement('li');
li.textContent = `${p.name} (${p.id_number})`;
ul.appendChild(li);
});
document.getElementById('loading').style.display = 'none';
});
</script>
没错,这里用了 AJAX。为啥不用 Django 模板渲染?因为产品经理总想加“实时搜索”、“动态筛选”,与其后期重构,不如一开始就前后端分离。虽然这会让运维多配个 Nginx,但值得。
数据库设计:别让测试同事半夜打电话
医疗数据最怕什么?脏数据。曾经有个实习生把 birth_date 设成 CharField,结果线上录入“1990年”、“1990-01”、“1990/01/01”三种格式,ETL 脚本直接炸了。
Django 的 DateField 能强制格式,但还不够。我们加个 model clean:
from django.core.exceptions import ValidationError
from datetime import date
def clean(self):
if self.birth_date > date.today():
raise ValidationError("出生日期不能晚于今天")
另外,索引很重要!患者列表按姓名查询?给 name 加 db_index=True。身份证号查重?unique=True 自动建唯一索引。
| 字段 | 类型 | 是否索引 | 说明 |
|---|---|---|---|
| id_number | CharField(18) | ✅ (唯一) | 身份证号,业务主键 |
| name | CharField(100) | ✅ | 姓名,常用于模糊搜索 |
| birth_date | DateField | ❌ | 除非高频范围查询,否则不建 |
上线前记得用 python manage.py sqlmigrate patients 0001 看生成的 SQL,确认索引是否生效。
生产环境那些坑
本地跑得好好的,一上生产就 502?我太懂了。
- 静态文件:Django 默认不服务 static 文件。生产环境必须配 WhiteNoise 或 CDN。
- DEBUG=False:很多人忘了关 DEBUG,结果 SECRET_KEY 泄露,被扫出 SSRF。
- 数据库连接池:默认 SQLite 只能单线程。生产必须换 PostgreSQL,并调优
CONN_MAX_AGE。
我们的部署流程是:GitHub Actions → Docker build → K8s。每次发版前,运维会盯着我说:“这次别再把 migrations 漏了啊!”——因为有一次我合并 PR 忘了跑 migrate,导致新字段查不到,凌晨三点被 PagerDuty 喊醒。
代码人生:从 CRUD 到架构思考
三年前我写 Django,只会 python manage.py startapp 然后狂写 views。现在,我会先画 ER 图、设计 API 响应结构、评估缓存策略。
Django 不只是个框架,它教会我用约束换安全。在医疗行业,一行错误的数据可能影响患者治疗。所以宁可牺牲一点灵活性,也要保证数据完整性。
最近看招聘,发现很多岗位要求 “Python + JS 全栈能力”。或许这就是趋势:后端不能只关心 ORM 和 serializer,也得懂前端怎么消费数据。所以我开始认真学 JavaScript 的异步处理、状态管理,甚至研究如何用 Web Workers 避免 UI 卡顿。
最后
这篇文章其实源于我准备面试时的复习笔记。如果你也正打算入坑 Django,记住:别怕文档厚,官方教程是最好的起点。遇到报错别慌,90% 的问题 Stack Overflow 上都有答案(剩下 10% 是你拼错了变量名)。
下周我可能会试试用 Django Channels 做实时通知——毕竟产品经理已经暗示“想要 WebSocket 支持”了。到时候再分享踩坑记录。
哦对了,如果你在医疗 IT 行业,欢迎交流!说不定哪天我们就在同一个会议室里,一起对着 Jira 里的 P0 Bug 抓狂呢 😅
代码人生,不止 CRUD。
—— 一个在 Mac 上敲代码、Windows 上擦屁股的 Python 开发

评论 0