Django入门教程:从嵌入式老狗到Python Web萌新的血泪实战

何浩宇
2025-12-19 11:58
阅读 1646

上周五晚上十一点半,办公室只剩我和运维小哥还在加班。他忙着处理线上告警,我则在跟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

最热最新
暂无评论
何浩宇Lv.1
0
影响力
0
文章
0
粉丝