Django入门教程:从嵌入式老狗到Python Web萌新的血泪实战
上周五晚上十一点半,办公室只剩我和运维小哥还在加班。他忙着处理线上告警,我则在跟Django的migrate死磕——报错信息赫然写着 django.db.utils.OperationalError: no such table: blog_post。那一刻我真的想把开发板焊枪拿出来,给这破数据库来个物理迁移。
别误会,我不是纯正的Web开发。我是从嵌入式转过来的,以前天天和STM32、FreeRTOS打交道,现在却要在公司新项目里用Django搭一个内部监控平台。入职才两个月,就被领导安排了这个“简单”的任务:“你不是会Python嘛?搞个网站展示下设备状态就行。” 好家伙,会Python和会Web开发之间,差了至少三个Kubernetes集群的距离。
但没办法,deadline就在下周三,产品经理已经在群里@我三次了。与其继续在C语言的内存泄漏里挣扎,不如硬着头皮上Django。这篇教程就是我在踩坑过程中记下来的实战经验,希望能帮到和我一样半路出家的朋友。
为啥选Django?而不是Flask or FastAPI?
说实话,一开始我想用FastAPI,毕竟性能好、异步支持强,符合我对“高效系统”的执念(嵌入式出身的通病)。但团队里没人熟悉它,而Django有现成的Admin后台、ORM、用户认证——这些对快速交付一个MVP太重要了。
而且我们公司用的是PostgreSQL,Django对它的支持堪称开箱即用。不像我之前在嵌入式项目里,为了省512字节RAM,连浮点运算都要手写查表。
实战:搭建一个设备状态展示站
我们的需求很简单:
- 显示所有IoT设备的在线状态
- 点击设备可查看历史数据(暂时只存最近10条)
- 后台能手动添加/删除设备
听起来像CRUD?没错,但正是这种“无聊”的项目最适合入门。
第一步:环境搭建(别跳过虚拟环境!)
# 老嵌入式人的习惯:先建个干净环境
python -m venv django-env
source django-env/bin/activate # Linux/Mac
# django-env\Scripts\activate # Windows,但我早就不碰Windows开发机了
pip install django psycopg2-binary # 别用sqlite!生产环境都是PostgreSQL
⚠️ 血泪教训:我第一次直接全局装Django,结果和系统里另一个项目的依赖冲突,debug到凌晨三点。从此我发誓:永远用虚拟环境。
第二步:创建项目和App
django-admin startproject iot_monitor
cd iot_monitor
python manage.py startapp devices
这里有个坑:Django的“项目”(project)和“应用”(app)是两个概念。你可以理解为:项目是整个产品,app是功能模块。比如我们还有个auth app管登录,api app提供接口。
第三步:设计模型(数据库结构)
作为硬件出身的人,我对数据结构特别敏感。设备表怎么设计?
# devices/models.py
from django.db import models
class Device(models.Model):
name = models.CharField(max_length=100, unique=True)
mac_address = models.CharField(max_length=17, unique=True) # "AA:BB:CC:DD:EE:FF"
is_online = models.BooleanField(default=False)
last_heartbeat = models.DateTimeField(null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"{self.name} ({'Online' if self.is_online else 'Offline'})"
注意几个细节:
unique=True防止重复设备last_heartbeat用来判断是否掉线(超过30秒没心跳就标离线)- 没用
IntegerField存状态码,而是直接用布尔值——简单清晰,符合嵌入式“状态机”思维
然后生成迁移文件并执行:
python manage.py makemigrations
python manage.py migrate
🤯 第一次运行
migrate时,我忘了改settings.py里的数据库配置,结果默认用了SQLite。上线前才发现,差点酿成事故。务必在settings.py里配好PostgreSQL:
# settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'iot_db',
'USER': 'your_user',
'PASSWORD': 'your_password',
'HOST': 'localhost',
'PORT': '5432',
}
}
第四步:写视图和模板
Django支持FBV(函数视图)和CBV(类视图)。我一开始用FBV,代码很快变得混乱。后来改用CBV,结构清晰多了:
# devices/views.py
from django.shortcuts import render
from django.views.generic import ListView
from .models import Device
class DeviceListView(ListView):
model = Device
template_name = 'devices/list.html'
context_object_name = 'devices'
ordering = ['-last_heartbeat'] # 最近活跃的排前面
模板也很简单:
<!-- devices/templates/devices/list.html -->
<h1>IoT设备状态</h1>
<ul>
{% for device in devices %}
<li class="{% if device.is_online %}online{% else %}offline{% endif %}">
{{ device.name }} - {{ device.mac_address }}
<span class="status">{{ device }}</span>
</li>
{% endfor %}
</ul>
配合点CSS,就能做出绿色(在线)/灰色(离线)的状态指示——是不是有点像串口调试助手的输出?
第五步:启用Admin后台(神器!)
# devices/admin.py
from django.contrib import admin
from .models import Device
@admin.register(Device)
class DeviceAdmin(admin.ModelAdmin):
list_display = ('name', 'mac_address', 'is_online', 'last_heartbeat')
list_filter = ('is_online',)
search_fields = ('name', 'mac_address')
然后创建超级用户:
python manage.py createsuperuser
访问 /admin,就能看到一个功能完整的管理界面!不用写一行前端代码,这就是Django的魅力。产品经理看到后直呼“这也太快了吧”,我内心OS:要是嵌入式也有这种轮子该多好……
生产环境注意事项(来自被运维教育后的反思)
虽然只是个内部工具,但我们还是按生产标准部署:
| 配置项 | 开发环境 | 生产环境 |
|---|---|---|
| DEBUG | True | False(否则会泄露敏感信息!) |
| ALLOWED_HOSTS | ['*'] |
['monitor.yourcompany.com'] |
| 数据库 | 本地PostgreSQL | 云数据库(带备份) |
| 静态文件 | 由Django服务 | Nginx托管 |
另外,千万别把数据库密码写死在代码里!我们用环境变量:
# settings.py
import os
DATABASES = {
'default': {
...
'PASSWORD': os.environ.get('DB_PASSWORD'),
}
}
然后用Docker或K8s注入密钥。运维小哥看到我这么干,终于没再翻白眼了。
心得体会:硬件人学Web的思维转变
最大的冲击不是语法,而是思维方式:
- 嵌入式追求“确定性”,Web接受“最终一致性”
- 硬件资源极度受限,Web更关注开发效率和可维护性
- 以前调Bug靠示波器,现在靠日志+Postman
但有些东西是共通的:比如状态管理。设备在线/离线就是一个典型的状态机,和嵌入式里的FSM如出一辙。
这次项目虽然简单,但让我意识到:技术栈只是工具,核心还是解决问题的能力。现在我已经能用Django快速搭出原型,甚至开始看Celery做异步任务了——虽然还是会在深夜怀念用JTAG调试的日子。
最后送大家一句我在工位贴的座右铭:“No bug is too small, no feature is too late.” (当然,前提是deadline还没到)
如果你也是从底层转上层,欢迎留言交流。顺便求推荐靠谱的Go Web框架,下个项目可能要用……(老板说要微服务化了 😅)
附:本文所有代码已整理到 GitHub Gist,包含完整
settings.py和Dockerfile。别直接复制到生产环境! 至少把DEBUG关了。

评论 0