Django入门实测:跑通官网8个Demo并用SimpleUI美化后台
Django 官网教程的第一课很多人是硬着头皮啃完的。八个大章节从模型写到测试再写到静态文件代码块密密麻麻新概念一个接一个不少同学看完一遍脑子里只剩“好像懂了但自己搭一个就卡住”。我在带新人和自己重刷官方文档的过程中反复验证了一个结论官网这套投票应用教程确实是最适合入门的路径但前提是你得先知道这 8 个 Demo 分别在练什么以及每一步的实际效果长什么样。这篇博文就围绕“实验一”展开——完整跑通官网 8 个 Demo再把默认的裸奔后台换成 SimpleUI 美化版整个过程会涉及环境搭建、模型设计、视图模板、表单交互、测试、静态文件、后台定制这些知识点所有步骤都以我本地实测为准。如果你正准备学 Django或者已经在教程里反复横跳但没串起来这篇文章可以当作一份带标注的路线图。我尽量把每一步背后的“为什么”讲清楚也会把我在实战中踩过的坑原样摆出来包括那些官网文档不会主动告诉你的细节。1. 官网 8 个 Demo 的递进逻辑别被章节数吓到Django 官网教程《编写你的第一个 Django 应用》一共有 8 个部分按主题可以拆成三条线数据线模型与数据库、交互线视图、模板、表单、工程线测试、静态文件、后台定制。很多人卡住是因为把它当成 8 个独立 Demo 在横跳实际上这套教材的编排是层层叠加的——第 1 个 Demo 创建的项目骨架到第 8 个 Demo 还在用。1.1 每部分 Demo 到底做了什么我按自己的理解把 8 个 Demo 重新梳理了一遍对应的核心产出如下章节核心任务练到的知识点Part 1创建项目和应用写第一个视图startproject、startapp、URLconf 初识、runserverPart 2配置数据库创建 Question 和 Choice 模型models.Model、字段类型、makemigrations、migrate、Django admin 初体验Part 3视图逻辑补全引入模板系统render()、模板变量、for循环、url反向解析、命名空间Part 4实现投票表单的提交与处理表单form、request.POST、get_object_or_404、reverse()、通用视图雏形Part 5为投票业务编写自动化测试TestCase、测试模型、测试视图、Client模拟请求Part 6自定义应用的静态文件与外观{% load static %}、CSS、STATIC_URL配置Part 7深度定制 admin 后台list_display、list_filter、search_fields、fieldsets、自定义后台类Part 8补充文档、历史记录等工程细节版本管理意识、Meta配置、admin 扩展技巧这样一拆就清楚多了前 4 个 Demo 是主流程——建项目、定义数据、展示页面、处理请求后 4 个 Demo 是在给主流程“上保险”——测试保证逻辑不会改崩、静态文件让页面能见人、后台定制提升管理效率。1.2 为什么不建议跳过任何一个 Demo我在社区里见过不少人学 Django 只看到 Part 2 就转头去做博客项目了理由是“投票应用太简单、不够实用”。这个想法可以理解但官网教程的价值恰恰在于它把 Django 的核心请求链路完整走了一遍。跳过 Part 5 测试的人最可惜。Django 的测试体系不是附加题它和视图、模型是同一套代码里的东西。官网 Part 5 用不到一百行测试代码就把Client、assertContains、reverse这些工具全带出来了。后面真正做项目的时候这些就是你的安全网——没有测试的 Django 项目改一个字段都可能把线上页面炸掉而且你还不知道是谁炸的。跳过 Part 7 后台定制的人也亏。Django admin 是很多人选择这个框架的重要理由但默认状态确实磕碜。Part 7 里教的list_display、list_filter、search_fields直接决定了你管理后台好不好用。想升级到 SimpleUI也是在这套自定义机制基础上加皮肤基础不牢后面美化也无从谈起。2. 环境准备与项目骨架版本坑不在少数官网教程默认你用的是最新稳定版 Django但“最新稳定”这四个字在不同年份含义完全不同。我这次实验用的是 Python 3.10 搭配 Django 4.2 LTS这个组合目前最省心——教程里的代码全部适用SimpleUI 的兼容也做得好。你要是用 Python 3.12 加 Django 5.x 也没问题但要注意后续某些第三方库是否跟上。2.1 创建项目的标准动作老规矩先建虚拟环境避免把系统 Python 搞乱mkdir django-lab cd django-lab python -m venv venv source venv/bin/activate # Windows 下用 venv\Scripts\activate pip install django装完之后验证一下版本python -m django --version然后创建项目和应用django-admin startproject mysite cd mysite python manage.py startapp polls这里有个很常见的坑项目名和应用名作用不同mysite是全局配置工程polls是具体的投票应用。Django 项目的标准组织方式是“一个项目包含多个应用”所以startapp polls之后你会看到mysite/和polls/两个目录平级千万别搞成嵌套的。2.2 settings 里先改这四样拿到新项目先别急着写代码打开mysite/settings.py把下面这几项处理好# 把新应用注册进来 INSTALLED_APPS [ django.contrib.admin, django.contrib.auth, django.contrib.contenttypes, django.contrib.sessions, django.contrib.messages, django.contrib.staticfiles, polls, # 新增 ] # 语言和时区 LANGUAGE_CODE zh-hans TIME_ZONE Asia/Shanghai # 静态文件 URL 前缀 STATIC_URL static/INSTALLED_APPS里加polls这一步我见过至少五个新手漏掉。漏掉之后的表现是模型建好、迁移也跑了但 admin 里看不到应用页面模板也找不到。Django 的自动发现机制依赖这个注册列表不是你把文件放进目录它就自动生效的。LANGUAGE_CODE改成zh-hans后admin 和表单报错信息会变成中文对初学者友好很多。TIME_ZONE改成Asia/Shanghai后模型里的DateTimeField自动记录的时间才是本地时间不然后续看数据会差 8 个小时。2.3 跑通第一个 Demo 的验证点创建完应用、改完设置先启动开发服务器看看能不能跑python manage.py runserver浏览器访问http://127.0.0.1:8000/看到火箭升空页面旧版本或默认欢迎页新版本说明环境没问题。再访问http://127.0.0.1:8000/admin会弹出一个登录框——默认 admin 界面长得很朴素但功能都在。这时你还没创建超级用户登录会报错执行python manage.py createsuperuser按提示输入用户名、邮箱、密码。这一步做完第 1 个 Demo 的目标就达成了项目能起、应用能建、后台能登。3. 投票应用核心链路模型到视图一个都不能少8 个 Demo 里Part 2 到 Part 4 是投票应用的主干流程。官网用“问卷 选项 投票”这个场景看起来简单但它覆盖了 Django 开发中最高频的三种操作定义数据结构、读取数据渲染页面、接收用户提交并写入数据库。这三个操作就是你日后做任何网站的基本功。3.1 模型设计的官网版本与我的注解打开polls/models.py官网给的是两个类from django.db import models class Question(models.Model): question_text models.CharField(max_length200) pub_date models.DateTimeField(date published) def __str__(self): return self.question_text class Choice(models.Model): question models.ForeignKey(Question, on_deletemodels.CASCADE) choice_text models.CharField(max_length200) votes models.IntegerField(default0) def __str__(self): return self.choice_textQuestion是问题表只有题目和发布日期两个字段Choice是选项表通过外键关联到Question加上选项文本和票数。__str__方法一定要写没有它你在 admin 后台看到的每个对象都是“Question object (1)”这种天书有了它才能显示成题目文本。官网在繁体中文版的教程里对on_deletemodels.CASCADE解释得比较简略这里多说一句这个参数表示当一个问题被删除时关联它的所有选项也一并删除。这个行为叫“级联删除”是数据库外键的经典语义。实际项目中有些外键语义是“删除主表时保留从表”或“置空”需要根据不同业务场景去调整但官网用CASCADE演示是最直观的。3.2 迁移的两个步骤为什么总有人说要跑两次模型写好后运行python manage.py makemigrations polls python manage.py migratemakemigrations是生成迁移文件它把模型的变化记录成一个 Python 文件放在polls/migrations/目录下你甚至可以打开看看里面是什么——其实就是 Django 描述数据库表结构的“施工图”。migrate才是真正把施工图应用到数据库在 SQLite 里创建对应的表。有人问为什么要分两步跑不能一步到位因为两步给了一个版本控制的节点你生成的迁移文件可以提交到 Git 里同事拉下来直接migrate就能同步数据库不需要重新makemigrations。如果直接改数据库哪天需要回滚就没有任何历史记录。这个设计思路和前端打包后生成版本文件是一样的道理——可追溯。如果想看 Django 实际执行的 SQL可以用python manage.py sqlmigrate polls 0001不放心的话可以用这个命令检查后面排查字段问题的时候很有用。3.3 用 shell 验证数据操作迁移完进 Django shell 做个快速冒烟测试python manage.py shellfrom django.utils import timezone from polls.models import Question, Choice q Question(question_text你最喜欢的编程语言, pub_datetimezone.now()) q.save() q.choice_set.create(choice_textPython, votes0) q.choice_set.create(choice_textJavaScript, votes0) q.choice_set.create(choice_textGo, votes0) # 查询所有问题 Question.objects.all() # 按日期过滤 Question.objects.filter(pub_date__ltetimezone.now()) # 通过外键反向查询选项 q.choice_set.all()choice_set是 Django 外键的反向关系名。你在Choice上定义了question ForeignKey(Question)Django 会自动给Question实例添加一个choice_set属性用来访问该问题下的所有选项。这个命名是自动的你也可以在ForeignKey里加related_namechoices改成q.choices.all()这种更简洁的写法。官网没提related_name但实际项目里几乎是必用的。3.4 视图函数的“请求-响应”模型Part 3 和 Part 4 的视图逻辑官网写得比较分散我合并成一条线来讲。投票应用四个视图首页展示问题列表、详情页展示某问题的选项、结果页展示当前票数、投票动作接收表单提交。代码大概长这样from django.http import HttpResponseRedirect from django.shortcuts import render, get_object_or_404 from django.urls import reverse from django.views import generic from .models import Choice, Question这里有个值得注意的点Django 视图函数不是“类方法”而是“接收请求对象、返回响应对象”的普通函数。你写的def index(request):request里装着 HTTP 方法、用户、表单数据、session 等一切信息你要做的是从里面取你需要的数据加工成HttpResponse返回给浏览器。这个模型理解透了后面不管是写 Django REST Framework 还是直接做前后端分离思路都一样。关键视图vote接收 POST 请求的逻辑是官网教程里最容易绕晕的一段def vote(request, question_id): question get_object_or_404(Question, pkquestion_id) try: selected_choice question.choice_set.get(pkrequest.POST[choice]) except (KeyError, Choice.DoesNotExist): return render(request, polls/detail.html, { question: question, error_message: 你没有选择任何选项。, }) else: selected_choice.votes 1 selected_choice.save() return HttpResponseRedirect(reverse(polls:results, args(question.id,)))这段代码演示了 Django 表单处理的三个关键点用request.POST[choice]读表单字段。注意这里 dict 取值方式如果字段不存在会抛KeyError所以要用try包住。校验失败时直接带错误信息重新渲染表单页。这个模式叫“渲染表单 错误反馈”是所有 Web 框架的通用套路。处理成功后用HttpResponseRedirect做重定向避免用户刷新页面时重复提交投票。“提交后重定向”是 Web 开发的最佳实践官网这里虽然没展开讲但代码里埋了很好的习惯。3.5 URLconf 的命名空间为什么不是可有可无polls/urls.py里官网定义了一个app_name polls然后每个路由用name起别名。这样做最大的好处是模板和视图里可以用{% url polls:detail question.id %}来代替硬编码的/polls/3/。你要是项目只做一次、以后不打算改路由那硬编码确实省事。但真实项目里路由地址经常要调整比如从/polls/3/改成/questions/3/你自己写死了那么多处 URL 就得一个一个找而用了反向解析只需改一处path定义。官网 Part 3 花了不少篇幅讲这个我用一个实际教训给你作注脚我第一次做企业站的时候因为图省事硬编码了十几个 URL后来客户要求路径里加个版本前缀我改了一下午全是无意义的体力活。4. 让后台从毛坯变精装SimpleUI 接入实录8 个 Demo 跑完投票应用的功能是完整了但每次打开/admin看到默认后台总有种“网站还没做完”的感觉。Django 默认 admin 不是不能用它的信息密度和组织逻辑其实是合格的只是视觉风格停留在上一个时代。SimpleUI 做的事情很简单不改变 admin 的底层逻辑只换一套现代 UI 皮肤顺带把侧边栏、首页看板、主题切换这些刚需功能补上。4.1 安装与注册顺序这一步能卡住九成人安装pip install django-simpleui然后在settings.py的INSTALLED_APPS里把simpleui放在django.contrib.admin之前INSTALLED_APPS [ simpleui, django.contrib.admin, # ... 其他内置应用 polls, ]这个顺序是硬性的。Django 加载 template 和 static 文件时会按INSTALLED_APPS的逆序查找同名资源simpleui之所以要排前面是为了让它的模板和静态文件覆盖掉 admin 的默认资源。顺序反了SimpleUI 的样式不会生效页面还是默认长相而且不报任何错误。改完保存重启runserver再打开/admin界面瞬间就不一样了——左侧出现可折叠的侧边栏登录页也变得现代不少。这一步的正向反馈非常强适合作为项目里的“小奖励”节点。4.2 几个值得立刻配置的 SimpleUI 参数SimpleUI 最讨喜的地方是它把常用配置都做成了settings.py里的常量。我实验时用到的配置如下# SimpleUI 配置 SIMPLEUI_HOME_PAGE https://www.djangoproject.com/ # 首页跳转地址 SIMPLEUI_HOME_TITLE Django 官网 SIMPLEUI_LOGO https://example.com/logo.png # 侧边栏 Logo SIMPLEUI_DEFAULT_THEME admin.lte # 主题可选值有 layui、admin.lte、e-blue 等 SIMPLEUI_ICON { 问题管理: fa fa-question-circle, 选项管理: fa fa-check-circle, }SIMPLEUI_HOME_PAGE很实用。默认情况下后台首页是 SimpleUI 自带的一个欢迎页可以把它指向你自己项目的某个统计页面或外部文档站点。对内部管理系统来说这个地方放一个操作手册或者数据看板的链接非常合适。主题切换是 SimpleUI 的一大卖点。SIMPLEUI_DEFAULT_THEME支持十几种预设主题从偏暗黑的dark_mode到偏商务的admin.lte都可以选。我实测下来admin.lte的侧边栏折叠和面包屑导航做得最顺手如果你有品牌色偏好在simpleui/static/simpleui/css/下直接覆盖变量也行但入门阶段用预设主题足够了。4.3 自定义菜单把后台变成你能做主的样子SimpleUI 默认会把 admin 里注册的模型按应用分组展示在侧边栏。SimpleUI 还支持用SIMPLEUI_CONFIG自定义菜单让你把常用操作放一起隐藏不常用的表SIMPLEUI_CONFIG { system_keep: False, menus: [{ name: 投票管理, icon: fa fa-th-list, models: [{ name: 问题列表, url: /admin/polls/question/, icon: fa fa-question, }, { name: 选项列表, url: /admin/polls/choice/, icon: fa fa-check, }] }] }这段配置的意思是在侧边栏新建一个“投票管理”菜单分组下面放两个子菜单分别指向问题模型和选项模型的管理页面。system_keep设为False后SimpleUI 不再自动展示 admin 现有的应用分组完全以你的自定义菜单为准。这个功能在模型一多的时候非常必要不然应用一多侧边栏会滚出天际。4.4 配合 Part 7 的后台定制效果才拉满SimpleUI 是把皮肤换了但它不影响 admin 本身的数据展示逻辑。你想要后台更好用还得靠官网 Part 7 教的那套自定义ModelAdminfrom django.contrib import admin from .models import Choice, Question class ChoiceInline(admin.TabularInline): model Choice extra 3 class QuestionAdmin(admin.ModelAdmin): fieldsets [ (None, {fields: [question_text]}), (日期信息, {fields: [pub_date], classes: [collapse]}), ] inlines [ChoiceInline] list_display (question_text, pub_date, was_published_recently) list_filter [pub_date] search_fields [question_text] admin.site.register(Question, QuestionAdmin)这套组合拳打下来后台的效果是SimpleUI 提供好看的皮肤和侧边栏QuestionAdmin提供“最后发布时间”“按时间筛选”“关键词搜索”这些实用能力而ChoiceInline让你在一个页面里同时编辑问题和它的选项不必来回切换。两者是叠加关系不是替代关系。5. 我在实战中踩过的坑与排查链路这次实验我特意没有用全新环境而是模拟了一个“已跟着官网教程跑完但没做任何额外配置”的中间状态。正因为这样后面接 SimpleUI 时踩了不少坑下面按我实际排查的顺序来写而不是直接给结果。你能看到问题是怎么一步步被定位的下次遇到类似的才有思路。5.1 坑SimpleUI 装完页面还是默认长相现象描述pip install django-simpleui成功settings.py里也加了simpleui重启服务后/admin页面毫无变化。排查链路第一步看INSTALLED_APPS的顺序。我最初把simpleui放在了最后Django 的静态文件查找覆盖规则是逆序所以 admin 默认的静态文件还是优先被找到SimpleUI 的资源根本没机会渲染。调整顺序后页面立刻变了。第二步如果顺序没问题看是不是浏览器的缓存。SimpleUI 的 CSS 和 JS 是通过 admin 页面加载的浏览器缓存可能把你留在旧版本的样式里。开发者工具里勾选 Disable cache 再刷新或者用无痕窗口看。第三步如果还是老样子看runserver的控制台有没有静态文件的 404 报错。有的话执行python manage.py collectstatic把 SimpleUI 的静态文件收集到静态目录。开发模式下虽然 Django 会自动搜应用内的 static但某些配置下还是会漏。5.2 坑admin 登录页变成了中文但模型列表页打不开现象描述设置LANGUAGE_CODE zh-hans后登录页正常显示中文但点进某个模型的管理页面时页面直接报TemplateDoesNotExist或者显示空白。排查链路这个问题通常是模板继承被某个第三方包干扰了。Django admin 的模板链是admin/base_site.html继承admin/base.htmlSimpleUI 接管后会把一套自己的模板加进去。如果某个依赖包也覆盖了 admin 模板且加载顺序不对就会炸。我先执行了python manage.py check确认没有明显的系统检查错误然后看控制台完整报错发现指向的是simpleui的某个模板文件缺失。最终解决方法是把simpleui升级到最新版老版本对 Django 4.2 的支持有 bug。这个教训是出现模板类问题时先升级到目标包的最新版再看是否兼容。5.3 坑migrate 时提示依赖冲突现象描述在跑到官网 Part 2 时执行python manage.py migrate报错信息里有类似Migration admin.0001_initial is applied before its dependency的文字。排查链路这个现象一般由两种原因造成一是之前执行过部分migrate但因为某些操作中断了导致数据库中django_migrations表里记录了部分迁移而实际表结构不完整二是手动改了数据库结构或删过迁移文件和迁移记录对不上。我的处理方法是python manage.py showmigrations这个命令会列出所有迁移的应用状态[X]表示已执行[ ]表示未执行。我发现了admin应用的一堆迁移显示[X]但对应的表并不存在。于是用python manage.py migrate admin zero重置 admin 的迁移状态再重新执行python manage.py migrate修复。如果是删除过迁移文件导致的冲突更常见的做法是直接删掉 SQLite 数据库文件重新来因为开发阶段数据不重要。但生产环境千万别这么干。5.4 坑模板渲染不对列表页出现一堆“Question object (1)”现象描述写完模板后页面能打开但列表里每项显示的是Question object (1)而不是问题文本。排查链路这个几乎可以肯定是__str__方法没写或者写了类没重新加载。Django 模板里{{ question }}默认调用对象的__str__()来显示。我在polls/models.py里补上__str__后刷新页面就好但如果你发现补了还没变检查一下是不是浏览器缓存了旧模板或者runserver没自动重启。这个坑单独拎出来讲是因为很多新手会误以为模板语法有问题翻遍模板文件也找不到原因其实问题出在模型端的__str__。5.5 坑表单提交后报CSRF verification failed现象描述投票表单点提交直接跳到错误页面写着CSRF verification failed. Request aborted.。排查链路Django 出于安全考虑要求所有 POST 表单必须携带一个{% csrf_token %}标签。忘记在form标签里加这个模板标签是所有 Django 初学者的必经之坑。解决方式是在表单内加上form action{% url polls:vote question.id %} methodpost {% csrf_token %} !-- 其他表单控件 -- /form官网教程 Part 4 的代码里其实已经带了{% csrf_token %}但如果你是从零手写表单很容易忽略它。这个机制背后的原理是Django 在服务端生成一个 token存在 session 里表单提交时带上这个 token服务端比对一致才认为是本站的请求。没有它任何网站都能往你的后台 POST 数据安全漏洞就是这么来的。6. 验收清单与后续扩展方向实验一做到这里功能上已经齐了。我在跑完整套流程后列了一份验收清单你可以对着检查自己有没有遗漏验收项验证方式预期结果项目启动python manage.py runserver首页可访问无报错admin 登录/admin输入账号密码成功进入后台且为 SimpleUI 样式模型展示后台点击“问题列表”显示默认问题数据字段齐全新增问题后台“问题管理”添加一条保存后列表出现新数据前端投票打开/polls/1/选择一个选项并提交票数 1跳转到结果页搜索过滤后台问题列表的筛选器和搜索框能按时间筛选、按文本搜索测试运行python manage.py test polls所有测试通过无 failure6.1 从实验一到真实项目还差这几步这个实验做完你已经具备独立搭建一个 Django 小系统的能力了。想往真实项目走我建议按优先级补下面这几块第一把 SQLite 换成 MySQL 或 PostgreSQL。开发阶段 SQLite 零配置很方便但部署到线上会面临并发写入和数据的限制。切换方式不复杂装mysqlclient或psycopg2改settings.py里的DATABASES配置即可模型代码几乎不用动。官网教程全程用 SQLite恰恰说明 Django 的设计目标是数据库无关的。第二给投票应用加一个“只允许登录用户投票”的权限控制。用 Django 自带login_required装饰器或者LoginRequiredMixin就能搞定这套机制在真实项目里天天用。第三把测试补全到覆盖所有视图。官网 Part 5 的测试只是开了一个头实际项目里至少要覆盖模型约束、视图跳转、表单校验这些核心节点。我在第一个真实项目里就是因为测试没跟上重构时把一个投票逻辑改坏了直到上线前一天才发现从那以后再也不敢不写测试了。6.2 关于实验过程的一点个人体会最后分享一个实操层面的小建议这份实验做完最好把polls应用里的代码重新读一遍重点看官方在Part 7里的QuestionAdmin和Part 3里的app_name把这两个作为“代码规范”的参考模板。我的经验是把这些约定刻进肌肉记忆比记一堆零散的知识点有用得多。后续不管做博客、做管理后台还是做 API 服务这套“模型定义 视图处理 admin 接管”的骨架会一直陪着你。