
Django 这个框架在 Python 圈里热了很多年到现在依然是 Web 开发绕不开的一个选择。不管你是在找工作、接外包还是想自己做个小产品Django 那套“自带电池”的完整方案都能让你少掉不少头发。这篇是基础入门的第一篇我打算把从环境搭建到跑通第一个查询、删掉一条数据这条线完整走一遍不讲虚的全是实操。适合刚学完 Python 基础、想正经做点 Web 项目的新手也适合那些之前用过 Flask、但对 Django 的“全家桶”风格还不太熟的开发者。我会先聊清楚 Django 的核心设计理念让你明白为什么它这么“重”却依然受欢迎然后带你亲手创建项目和应用写第一个视图把 ORM 里的查询和删除对象这两个关键操作掰开揉碎了讲透最后再整理一批新手最容易踩的坑。整个过程我会把我自己平时怎么搞的都写出来包括哪些命令必须跑、哪些不起眼的小习惯能救你命。1. 为什么第一篇要讲框架底子1.1 Django 到底解决什么问题很多教程上来就是“安装 Django、创建一个项目、跑起来”但你没想清楚它帮你解决了什么后面越学越糊涂。Web 开发说穿了就是几件事接收 HTTP 请求、提取参数、处理数据、返回响应页面或 JSON。如果纯粹用 Python 手动写你得自己解析请求头、管理 Cookie 和 Session、处理数据库连接池、防注入、写模板引擎……每件事都是一个独立的深坑。Django 的意义在于把这堆日常 Web 开发里高度重复的工作全部标准化封装好了。我第一次用 Django 的时候有一个很直观的感受它像一个施工规范特别严的装修队虽然前期看起来规矩多——必须按它这套目录结构来、类得这么写、迁移得这么做——但你后期改需求、加功能反而越来越轻松。因为代码结构统一了团队里的人不用解释太多就能互相接手。这个“约束带来的自由”就是 Django 从头到尾都在坚持的设计哲学。另外要提一下它的 MVT 架构Model、View、Template。你别死记字母可以打个比方Model 是仓库管理员负责跟数据库打交道它知道货物数据长什么样、放在哪View 是柜台服务员你提出要求他转身找仓库管理员拿数据再决定给你展示什么Template 是菜单模板规定展示的样式。请求来了View 去 Model 查数据再把数据塞进 Template返回给用户。整个流程非常清晰新手只要记住“数据进出都在 Model业务判断都在 View页面渲染都在 Template”就够了。1.2 初学者选框架得看重什么选 Web 框架没有绝对的好坏只有适不适合。我一直给新手的建议是如果你希望快速做出能上线的东西而不是反复折腾底层细节Django 是比 Flask、FastAPI 更合适的第一选择。Flask 走的是“够用就好”的路子一切自己拼今晚装 Flask明天可能就要装数据库扩展、表单扩展、登录扩展……每个扩展都有自己的坑串起来更坑。FastAPI 呢性能好、异步生态强但它对设计模式没有强制约束新手容易写出一坨不好维护的代码。Django 是另一条路它把大件家具基本都给你配齐了ORM、Admin 后台、表单处理、认证系统、中间件、信号全都内置你只需要考虑业务怎么写。有人担心学 Django 是不是太重太复杂我倒觉得这种担心反了。它的复杂是“有序的复杂”每个模块有明确分工文档里写得清清楚楚。反而是那种“什么都要自己装”的路子看着简单实际坑多到你怀疑人生。我给初学者列过一张表你们可以参考对比项DjangoFlaskFastAPI学习曲线初期略陡后期平缓初期平缓后期陡中等异步概念有门槛内置功能极全ORM、Admin、Auth、表单极少需自行搭配较少侧重 API适合场景内容站、管理系统、中大型业务小型服务、微服务高并发 API、AI 服务生态规范强约束结构统一自由度高风格各异偏现代但约束少新手友好度高跟着规范走不容易乱中自由度过高容易踩坑中低要求懂的东西较多不是说 Flask、FastAPI 不好而是对“项目实战新手”来说Django 给的这份确定性能让你把有限的脑力花在业务和代码质量上而不是耗在组合各种第三方库上。2. 环境准备从零搭出 Django 运行环境2.1 为什么一定要用虚拟环境我见过太多人在这一步就翻车直接在系统 Python 里 pip install django装了一堆乱七八糟的包后来某个项目要 Django 3另一个要 Django 5互相打架最后只能重装系统解决。这就像你把所有衣服都塞进一个柜子里春夏秋冬混在一起换季时候翻半天找不着衣服还经常把冬天的毛衣当成夏天的 T 恤往外拿。虚拟环境就是给每个项目单独分一个衣柜。在 Python 里最常用的是venv模块Python 3.3 之后就内置了不需要额外安装。你进入虚拟环境后pip 安装的包都只对这个项目生效系统 Python 干干净净项目之间也不会互相污染。Python 版本方面我建议直接用 Python 3.10 或更高的稳定版本。Django 老早就不支持 Python 2 了现在官方推荐的就是 Python 3。别用那种系统自带的旧版本 Python版本太老很多新特性用不上Django 最新版可能直接装不上。2.2 安装 Django 的核心命令与验证整个过程其实就几条命令我一步步写出来。先在项目目录下创建虚拟环境python3 -m venv venv这条命令会创建一个叫venv的目录里面就是独立的 Python 运行环境。注意 macOS 和 Linux 上用python3Windows 上可能是python或py -3自己根据实际情况调整。激活虚拟环境# Windows venv\Scripts\activate # macOS / Linux source venv/bin/activate激活之后你的命令行最前面会出现(venv)前缀这就代表你已经进入了独立的项目环境。然后安装 Djangopip install django验证是否装好python -m django --version这一步会显示出你当前安装的 Django 版本号比如5.0.x。如果能看到版本号恭喜环境已经通了。这里有个小细节可能新手不知道pip装的是最新版如果你想装指定版本比如长期维护版可以写pip install django4.2。装特定版本不是没事找事很多时候项目要部署到服务器服务器环境不一定支持最新版锁定版本反而更稳。注意别在激活虚拟环境之前执行python -m django --version。我第一次没激活环境就运行系统提示找不到模块我还以为是 Django 没装上其实是环境搞错了。这种低级错误排查起来比解决问题本身还花时间。3. 创建项目和 App先搞清它的目录设计3.1 startproject 到底创建了什么装好 Django 之后第一件事就是创建项目。注意项目名别用 django、test 这类关键词免得后面出诡异问题。我一般用一个描述性的名字比如myblog或者mysite简单清楚。在虚拟环境激活状态下运行django-admin startproject mysite如果你只是执行了django-admin却提示命令找不到大概率是虚拟环境没激活或者 pip 安装路径没进 PATH。重新激活环境再试一次就行。运行之后会生成一个mysite目录里面结构是这样的mysite/ ├── manage.py └── mysite/ ├── __init__.py ├── settings.py ├── urls.py ├── asgi.py └── wsgi.pymanage.py是项目的“遥控器”以后所有管理命令都要从这里跑。内层的mysite/叫项目配置目录里面settings.py是全局配置中心数据库、App 注册、静态文件、模板路径全在这里配。urls.py是整个项目的 URL 分发表相当于物流站的调度中心哪个请求该去哪。wsgi.py和asgi.py是部署到服务器时用的入口开发阶段不用管它。第一次看到这个结构你可能觉得“怎么这么多文件”但这就是 Django 的规范。它把配置集中在项目目录把业务代码分散到各个 App后面你就会体会到这种拆分的价值。3.2 创建 App 的正确姿势项目创建完要创建一个具体的功能模块也就是 Django 里的 App。这一套操作我建议你亲手敲一遍不要复制粘贴敲一遍印象才深。在项目根目录下运行python manage.py startapp blog这里我以博客应用blog为例。创建完项目目录变成这样mysite/ ├── manage.py ├── mysite/ │ └── settings.py └── blog/ ├── __init__.py ├── admin.py ├── apps.py ├── models.py ├── tests.py └── views.pyblog/目录里面是 App 的核心文件。models.py放数据模型views.py放视图函数admin.py用来注册后台管理界面tests.py写测试全部各司其职。这里有个非常经典的坑创建完 App 之后很多人忘了把它注册到settings.py。光创建不注册Django 根本不知道有这个 App 存在你会遇到“表不存在”“URL 导入失败”之类的奇怪报错。必须打开mysite/settings.py找到INSTALLED_APPS列表把blog加进去INSTALLED_APPS [ django.contrib.admin, django.contrib.auth, django.contrib.contenttypes, django.contrib.sessions, django.contrib.messages, django.contrib.staticfiles, blog, ]注册完你的 App 才算真正被项目接纳。我在公司带人的时候几乎每个新人都在这卡过至少一次你们可别重蹈覆辙。4. 写第一个视图理解 URL 路由的流转逻辑4.1 从四行代码到一个页面项目创建好了App 也建了接下来得让它真正跑起来。先打开blog/views.py写一个最简单的视图函数from django.http import HttpResponse def index(request): return HttpResponse(你好Django)这段代码的意思很直白定义了一个index视图函数接收一个request参数里面装着用户的全部请求信息然后返回一个包含文本的 HTTP 响应。它目前不碰数据库不读文件就是一个最原始的页面。但光写视图还不够你得告诉 Django当用户访问某个 URL 时应该调用这个函数。所以要在 App 目录下新建一个urls.py文件注意这个文件不会自动生成要你自己创建写from django.urls import path from . import views urlpatterns [ path(, views.index, nameindex), ]path(, ...)表示空路径也就是访问 App 首页时触发这个视图。nameindex是给这个路由起个名字后面模板里写链接会用到。最后把这个 App 的urls.py挂到项目的urls.py里。打开项目目录下的urls.py改成from django.contrib import admin from django.urls import include, path urlpatterns [ path(admin/, admin.site.urls), path(blog/, include(blog.urls)), ]include(blog.urls)的意思是凡是访问路径以blog/开头的请求都交给blog/urls.py里的urlpatterns去分派。这样项目可以挂很多 App每个 App 管好自己的 URL互不干扰。4.2 跑起来亲自看一眼结果在项目根目录有manage.py的那个目录运行python manage.py runserver看到类似下面的输出就说明服务起来了Watching for file changes with StatReloader Performing system checks... System check identified no issues. You have 1 unapplied migration(s). Django version 5.0.x, using settings mysite.settings Starting development server at http://127.0.0.1:8000/它在http://127.0.0.1:8000/上开了一个本地服务。你打开浏览器访问http://127.0.0.1:8000/blog/就能看到“你好Django”这一行字。还没看到页面前先提醒一个细节runserver是个开发服务器它会在你保存代码后自动重载非常方便。但你要是往视图里扔了个语法错误页面会显示帮你排错的大篇幅错误页这个错误页在调试时是宝在生产环境可千万别开具体原因后面讲部署再说。第一次跑起来的时候你可能遇到端口被占用的问题错误提示通常是Error: That port is already in use.。解决办法是换一个端口python manage.py runserver 8001开发阶段想用哪个端口都行只要不跟系统其他服务冲突。这个细节估计很多教程不讲但我实测真的会碰到而且是新手必踩的坑。注意不要把include和path的导入顺序搞混。有人偷懒写成from django.urls import path, include顺序无所谓但忘了include下面引用include(blog.urls)的时候就会直接报NameError。这类报错信息很直接看到别慌对照导入语句检查即可。5. ORM 核心操作定义模型、查询数据、删除对象5.1 为什么说 ORM 是新手的第一道坎Django 的 ORM对象关系映射是这套框架里最值得花时间学的部分。在你没接触它之前操作数据库要么直接写 SQL要么用各种数据库客户端工具一切都要靠字符串拼接 SQL 语句。而 ORM 做的事就是让你用 Python 的类和对象来操作数据库表。我举个例子。你在传统方式下要查某个用户的信息可能要写SELECT * FROM user WHERE username 张三然后用数据库驱动把结果转换成 Python 字典。到了 Django 里你先在models.py定义一个类对应数据表之后只需要写User.objects.filter(username张三)拿到的就直接是 Python 对象属性直接用点号访问不用再手动转。这中间省掉了大量样板代码也顺带帮你防住了 SQL 注入——因为查询参数是框架帮你处理的。ORM 最大的好处是你从头到尾都在用 Python 思考不用反复切换心智模型。坏处是当你真的需要一些复杂 SQL 时ORM 的表达力可能不够得写原生 SQL。但作为第一篇入门文章你先掌握 ORM 的常规操作完全够用了。5.2 定义一个博客文章的模型类我们继续用上面的blogApp 来演示。打开blog/models.py写一个最基础的Article模型from django.db import models class Article(models.Model): title models.CharField(max_length200) content models.TextField() created_at models.DateTimeField(auto_now_addTrue) updated_at models.DateTimeField(auto_nowTrue)你逐行看一下title用CharField对应数据库里的变长字符串max_length200是必填参数。content用TextField对应大段文本。created_at用DateTimeFieldauto_now_addTrue表示插入时自动填入当前时间之后不再更新。updated_at同样用DateTimeFieldauto_nowTrue表示每次保存对象时都自动更新为当前时间。这四行代码生成的数据库表会有自增主键id、标题、内容、创建时间、更新时间这几个字段。你不用写一句 SQLDjango 全帮你搞定。定义完模型要生成数据库表还得做两步。第一步生成迁移文件。迁移文件可以理解为“数据库修改说明书”把它提交到版本控制里团队其他人一执行就算挂上同样的表结构python manage.py makemigrations blog你会看到类似输出Migrations for blog: blog/migrations/0001_initial.py - Create model Article第二步执行迁移真正把表建出来python manage.py migrate这一步会同时执行 Django 自带的那些 Appadmin、auth 等的迁移以及你刚生成的blog迁移。执行完数据库里就有了blog_article这张表。提示很多新手在这两步之间会忘掉migrate导致后面操作数据时报“表不存在”。记一个心法makemigrations是“起草文件”migrate是“正式盖章生效”。两个都跑了才算完事。5.3 查询对象all、filter、get 的区别与注意点模型建好现在往里面加几条数据。最方便的是用 Django shell它就是一个在项目环境中运行的 Python 交互式命令行。运行python manage.py shell然后逐行输入from blog.models import Article Article.objects.create( title第一篇博客, content这是 Django 入门的第一篇文章。, ) Article.objects.create( titleDjango 的 ORM 很强, content用 Python 对象操作数据库就问你爽不爽。, )现在查一下数据articles Article.objects.all()objects.all()返回的是 QuerySet可以理解成一个“懒加载”的数据库查询集合。你注意这点它并不代表数据已经全部取到内存里了而是在你真正用它的时候Django 才会去执行查询。比如你循环它for article in articles: print(article.title, article.content)这时才会真正访问数据库。这种惰性求值不是为了炫技是为了让你在构建复杂筛选时不会因为多写几行代码就去数据库多跑几次性能提升非常明显。再看filter。它是用来按条件筛选的返回的是 QuerySet可能有多条也可能是空集you_articles Article.objects.filter(title__containsDjango) print(you_articles.count())filter(title__containsDjango)翻译成 SQL 大概是WHERE title LIKE %Django%。注意这里的双下划线__contains是 Django 查询语法的标志不要说漏了。然后是get。它用来获取单个对象注意它跟filter有个关键区别get返回的是对象本身不是 QuerySet而且如果找到多个或没找到它会直接抛异常。比如article Article.objects.get(id1)如果 id 为 1 的记录不存在会抛DoesNotExist如果查到多条会抛MultipleObjectsReturned。我要强调这一点是因为太多新手在这栽过用filter之后没意识到它返回的是列表式的 QuerySet直接当对象用报错说没有title属性或者该用get的时候用了filter拿到一个 QuerySet 后发现无法直接取.content。我的习惯是明确只查一条记录时用get然后立刻在异常处理里兜住可能会查多条或不确定条数时用filter不要混用。5.4 删除对象delete 的正确用法与后果“django执行查询-删除对象”这个搜索词说明很多人在删除这条路上踩了坑。删除对象在 Django 里其实非常简单但有一些细节必须注意。先演示最基础的方式。拿到一个对象然后调它的delete()方法from blog.models import Article article_to_delete Article.objects.get(id1) article_to_delete.delete()执行完这条delete()方法会返回一个包含删除数量的信息元组同时数据库中 id 为 1 的记录就没了。再用filter批量删除Article.objects.filter(title__containsDjango).delete()这会把所有标题包含 “Django” 的文章一次性删掉。filter(...).delete()返回的被删除对象数量会更大如果涉及关联数据Django 会自动处理级联删除默认是CASCADE行为也就是被关联的数据也一并删除。删除对象有几个坑我挨个给你排一下第一个坑是“删除后的对象还能访问”。执行delete()之后代码里的变量article_to_delete仍然存在你还能访问它的属性甚至print(article_to_delete.title)也能打出来。但这只是 Python 对象还存在数据库里已经没了。新手容易误以为删除没成功反复执行多遍。判断是否真的删除了应该重新查库try: Article.objects.get(id1) except Article.DoesNotExist: print(记录已经不存在了)第二个坑是“误删数据不可逆”。你在开发环境删错了大不了重新创建个测试数据。生产环境要是手滑执行了批量删除那可真的大条了。我建议生产环境操作删除之前先执行同样条件的filter查询把结果数打出来看一眼确认数量符合预期再执行delete。比如q Article.objects.filter(title__containsDjango) print(q.count()) # 先看会删几条 q.delete() # 确认后再删第三个坑是“外键级联删除”。如果你的模型设置了外键关联比如每篇文章都有作者删除作者时默认会把该作者的所有文章一起删掉。这个行为有时候你并不想要。如果你要保护这些数据可以在定义外键时设置on_deletemodels.PROTECT这样当你尝试删除还有关联记录的作者时Django 会抛出ProtectedError阻止你操作。author models.ForeignKey(Author, on_deletemodels.PROTECT)一句话总结删除操作很简单但删除决策要慎重。能先查后删的一定先查后删。6. 新手实战最常见的坑与排查技巧6.1 从“项目实战新手”视角看第一步最容易出问题热词里出现了“django项目实战新手”说明从这个阶段过来的人非常多。项目实战跟跟着教程敲代码完全是两个体验教程是确定性的中间不会突然报错实战是你自己设计、自己实现各种问题接踵而来。我观察下来新手真正开始写独立项目时遇到最多的其实是三类问题。第一类是“不知道怎么把功能拆成 App”。比如你做一个功能多一点的博客文章是一个 App用户账户管理是不是要拆一个 App评论要不要单独拆我的建议是先按领域边界拆别按页面拆。文章、用户、评论这些东西都有独立的数据模型和业务逻辑拆成blog、users、comments是合理的。不要为每个页面都建一个 App那样只会让目录爆炸。第二类是“ URL 和视图对不上”。写完视图却访问不到大部分情况是urls.py里没include或者path里的路径写错了。排查思路很简单先把python manage.py runserver启动看它在访问时输出的请求日志再回浏览器看 404 和 500 页面基本能定位问题在哪一层。第三类是“数据库迁移报错”。比如你改了模型字段忘了生成新迁移数据库结构和模型不匹配操作时报no such column。这时候就跑python manage.py makemigrations、python manage.py migrate两条指令问题多半就解决了。6.2 实战中容易忽视的 Django 命令与调试技巧除了runserver新手一定要记几个命令我列个清单命令作用使用频率python manage.py startapp 应用名创建 App项目初期python manage.py makemigrations生成迁移文件每次改模型python manage.py migrate执行迁移每次生成迁移后python manage.py shell进入项目环境交互命令日常调试python manage.py createsuperuser创建后台管理员Admin 相关python manage.py collectstatic收集静态文件部署阶段createsuperuser我要单独提一下。Django 自带一个后台管理系统就是 Admin访问路径是http://127.0.0.1:8000/admin/。进入后台前要创建管理员账户python manage.py createsuperuser按提示输入用户名、邮箱、密码密码不显示在屏幕上完成后就能用这个账户登录后台。让你创建的 App 出现在后台里只需要到blog/admin.py里注册from django.contrib import admin from .models import Article admin.site.register(Article)这个后台的好处是零成本的数据管理界面适合快速维护数据也适合新手直观看到数据库里到底有什么内容。而且它跟热词里的 “django unfold” 还能联动——Unfold 是一个第三方后台美化扩展装上之后 Admin 界面从“原始操作台”变成“现代仪表盘”。不过那是后面进阶的内容第一篇先把原生后台用明白再说。再说一个调试技巧开发时会遇到那种“明明没改代码页面却报错”的情况。首先确认runserver的窗口里有没有显示“检测到文件变化并重载”。有时候你改的文件路径不对或者改的只是配置文件但没重启服务还在用旧代码。一个最笨但最有效的办法重启runserver。很多奇怪的问题一重启就好了。6.3 我踩过三次才记住的两个操作习惯最后聊两个我自己的经验不是那种教程会写的内容但真的很能救命。第一个习惯是每次做实验或练习前给数据库做个备份。Django 提供了dumpdata命令可以把数据导出成 JSON 文件python manage.py dumpdata mydata.json真要搞砸了想恢复数据就执行python manage.py loaddata mydata.json删对象、改字段这种操作再怎么小心都不为过。有个备份在你操作起来心态完全不一样。第二个习惯是不要用python manage.py runserver跑生产环境的服务。开发服务器性能差、安全屏障低、还有自动重载它存在的意义是让你写代码时方便。真到上线部署要用 Gunicorn 或者 uWSGI搭配 Nginx 来做静态文件处理和反向代理。这篇是入门我点到为止但它一定是你后面会碰到的墙提前知道方向没错。7. 第一篇的终点你已经走通了 Django 的最小闭环从安装虚拟环境到创建项目、创建 App、写视图、配路由再到定义模型、执行迁移、查询数据、删除对象一个 Django 开发的最小闭环你已经完整跑通了。这个闭环非常重要因为之后你学的所有东西——模板渲染、表单处理、用户认证、API 开发——都是在往这个骨架里填肉。我个人在实际操作中的体会是Django 入门阶段最大的难点不是某个函数不会用而是搞不清“系统是怎么流转的”。只要你理解了“请求进来URL 分发给 ViewView 通过 ORM 操作数据库拿到的数据再渲染返回”这条主线剩下的都是查文档的事。按你目前的基础接下来很适合做三件事一是把 Admin 后台里注册好文章模型试着用手动添加数据的方式再巩固一遍 ORM二是把查询条件从title__contains扩展到created_at__gte、id__in这类常用筛选写法三是去搜一下 “django unfold” 的接入方法给自己的后台换一张好看的脸增加一点继续学下去的兴趣。还可以顺便体验一下现在很流行的一种学习方式——用 AI Agent 辅助生成 Django 代码让大模型先给你生成一个带 CRUD 的小项目骨架你再逐行看懂它学习效率会快很多。但有一个前提你自己必须能看懂它生成的每一行代码不然 AI 帮你写的代码就是个黑盒出错了你连从哪里断点都不知道。我是建议你赶紧把手上的项目跑起来哪怕只是一个“能存文章、能删文章”的小网站。等这个最小流程真的跑在你的电脑上你再看任何 Django 教程都会比没动手前清楚得多。下一篇我打算讲讲模板和视图的配合把“动态渲染页面”这块补上到时候欢迎继续来看。