
很多人问过我一个问题Django到底是什么尤其在Python圈子里这个框架几乎绕不开——找工作看JD上面写着熟悉Django者优先刷技术社区满屏都是Django项目实战随手搜Python Web教程十有八九也用它。但真要说清它能干嘛、为什么这么火、自己和它什么关系我见过不少上手写过几年脚本的人照样支支吾吾。Django从2005年发布到现在已经快二十年了依然活跃在各类Web项目的前线。它官方的宣传语是The web framework for perfectionists with deadlines为追求完美且有截止日期的人准备的Web框架这句话翻译成人话就是它帮你把Web开发里最繁琐、最容易出错的部分全部打包解决让你把精力集中在业务逻辑上。这篇内容就是给那些刚接触Python、被框架两个字吓住的新手以及写了几年业务代码但没系统梳理过Django的老手看的我会把它拆开揉碎从它到底解决了什么问题、装好一个项目要几步、模型视图模板怎么配合工作、日常增删改查怎么玩一直聊到它在真实企业项目里该承担什么角色。1. 先解决最底层的问题Django到底是个什么东西框架这个词是很多人跨不过去的第一道坎。你背过函数、写过脚本、知道怎么用requests抓个网页但一听到框架就开始慌觉得是个很高深的东西。其实没你想得那么玄乎。我举个生活里的例子。你今天要开一家小饭馆可以亲自买菜、洗菜、切菜、砌灶台、装修店面、设计菜单这是自己搭全套。你也可以直接租一间已经通好水电、装好炉灶、甚至连菜谱模板都给你备好的商铺你只需要选好招牌菜、洗干净盘子、把客人伺候好就行。Django就是后者。它是一个已经帮你把水电管线HTTP协议处理、灶台URL路由、传菜流程请求-响应机制、甚至库存系统数据库操作全部备好的厨房你要做的是往里面填你的菜谱——也就是业务代码。从技术术语上讲Django是一个重量级的Python Web框架它遵循MTVModel-Template-View模型-模板-视图架构模式。重量级不是说它跑得慢而是说它自带的功能非常多、非常全。它内置了ORM对象关系映射、Admin后台管理、Form表单处理、用户认证系统、安全防护防XSS、CSRF、SQL注入、模板引擎、缓存框架、国际化支持几乎你能想到的Web开发通用需求它全给你塞进来了。这就是大家常说的全家桶。这时候你可能疑惑功能这么全是不是很难学恰恰相反。对一个刚从脚本思维转向Web开发的新手来说Django的全家桶反而是最友好的——因为你不必去调研这个功能用哪个库那个功能怎么整合框架都替你选好了一条最稳妥、最标准的路径你遵循它的约定去写就完了。相比之下Flask那种微框架就像一间毛坯房自由度高但什么都得自己装马桶是你自己买的、水管是你自己接的对新手来说反而是负担。为什么全球有这么多开发者用它从Instagram到Pinterest、从Mozilla到国内不少企业级应用都在跑Django就因为它解决了Web开发里一个永恒的痛点重复造轮子。同样的登录逻辑、同样的后台管理、同样的数据库增删改查你每接手一个新项目都要重写一遍不累吗Django直接把这些沉淀成了框架内置的东西让你从第一天开始就在写业务逻辑而不是在写基础设施。1.1 从MVC到MTVDjango的架构设计你可能在网上看到过MTV这个词有点懵不是都说MVC吗你的疑惑很正常。MVC是Model-View-Controller模型-视图-控制器的缩写而Django的MTV对应的是Model-Template-View。名字看着差不多其实有对应关系但不完全一样。按Django的官方定义它自己就是MVC框架只是把传统MVC里的View视图改叫了Template模板把传统MVC里的Controller控制器改叫了View视图。你记一个大概的对应关系就行传统MVC的模型对应Django的模型传统MVC的视图对应Django的模板传统MVC的控制器则大体对应Django里视图函数和URL配置的组合。那么这三个角色各负责什么我拿前端开发里最熟悉的用户提交一个表单来举例。用户填写了一个商品入库表单点了提交。这时候Django的URL路由先发挥作用它像个前台接待员看清请求地址后把你带到对应的视图函数那里。视图函数接到请求后读到表单数据调用Model模型去跟数据库沟通——写入一条商品记录。数据库操作完成后视图函数把结果打包交给Template模板渲染成一个漂亮的HTML页面然后返回给浏览器展示给用户。整个过程里Model管数据、Template管展示、View管调度。你不需要在HTML页面里写复杂的SQL也不需要把数据库返回的数据手动拼成字符串每一层各司其职代码自然清晰。这也是新手最容易混淆的地方——一上来就试图理解视图到底在哪个文件里写模板又是干嘛的其实多写两个项目就通了。1.2 为什么说它是带护栏的全家桶我还想给你打个预防针。很多人抱怨Django太重约束太多这种声音主要集中在只做过小型脚本、没经历过大型项目的人身上。约束多恰恰是Django最大的优点。比如它强制你按Model、View、Template的目录结构组织代码新手可能觉得烦但如果你接手过那种代码堆在一个文件里、几万行乱成一团的项目你就能体会到Django的约定优于配置是在保护你。就好比高速公路有车道线你开车不觉得被约束反而觉得安全真正可怕的是没有车道线的地方看起来自由实则处处是坑。项目到了一定复杂度Django的强约束能帮你把代码维持在一个健康的组织结构里这对团队协作和长期维护是决定性的。2. 从零装一个Django项目环境准备与目录结构理论知识永远是抽象的咱们直接动手。这一节我带你从空环境一路跑到页面显示Hello Django同时把Django项目里那些看起来奇奇怪怪的目录、文件一次性讲明白。顺带说一句网上有个高频搜索词叫怎样安装django可见这一步卡住了不少人——不是卡在技术上而是卡在不知道装了什么、装到哪了。先说环境。强烈建议你在装Django之前先建一个虚拟环境尤其当你的电脑上还有别的Python项目的时候。Python的包管理就像往书包里塞东西你每个项目都往全局环境里pip install过几个月就会变成一锅粥项目A要Django 4.2项目B要Django 5.0全局环境里却只有旧版本一个装新的就把旧的顶掉项目A就崩了。虚拟环境相当于给每个项目开一个独立的小房间互不干扰。创建并激活虚拟环境、安装Django的命令在Windows和macOS/Linux下略有不同我列一下核心命令# macOS / Linux python3 -m venv venv source venv/bin/activate # Windows python -m venv venv venv\Scripts\activate # 激活后安装Django pip install django装完建议顺手升级一下pip用python -m pip install --upgrade pip不然装第三方包时偶尔会踩到依赖解析的坑。安装完成后你可以用python -m django --version确认版本号。这里提醒一句Django 4.x和5.x都需要Python 3.10或更高版本如果你的系统自带的还是Python 3.x老版本先更新Python再玩Django不然装不上。2.1 startproject创建项目骨架环境就绪后在命令行里进入你想放项目的目录执行django-admin startproject myproject cd myproject这一步会生成一个项目骨架你尽量记住它的结构这是你今后和Django朝夕相处的地方myproject/ manage.py # 项目命令行入口所有管理命令都靠它 myproject/ __init__.py # 声明这是一个Python包 settings.py # 项目配置文件数据库、应用、中间件都在这注册 urls.py # 全局URL路由表请求进来先到这里分派 asgi.py # 部署到异步服务器时的入口 wsgi.py # 部署到传统Web服务器时的入口2.2 startapp创建应用一个项目可以有多个应用项目骨架做完接下来是创建应用。Django里有个概念你从第一天起就要理解清楚项目Project和应用App的区别。一个项目相当于一个大超市应用相当于超市里的各个部门——生鲜部、日化部、收银处。一个Django项目通常包含多个应用比如一个电商网站用户管理是一个App商品管理是一个App订单管理又是一个App。它们通过项目的settings.py统一配置、协同工作。创建应用的命令是python manage.py startapp products执行后项目里多出一个products/文件夹里面有models.py定义数据模型、views.py定义视图逻辑、migrations/数据库迁移记录、admin.py注册后台管理、apps.py应用配置等文件。到这里你已经完成了一个Django项目最原始的骨架搭建。很多人卡在创建了app但页面还是404这个坎上多半是忘了在settings.py的INSTALLED_APPS里注册应用。打开myproject/settings.py找到INSTALLED_APPS列表加上products这个名字Django才会认识你这个新应用。2.3 跑起来看第一个页面配置完成后先别急着写业务代码。启动一下开发服务器验证你的环境和项目骨架是否健康python manage.py runserver看到命令行输出But your browser doesnt work相关的提示别慌那是提示你浏览器地址访问不对。默认地址http://127.0.0.1:8000/会显示一个带火箭图标的欢迎页这就说明项目已经跑起来了。runserver是Django自带的重启式开发服务器你改代码它自动热加载相当省心。跑通第一个页面这个目标别急着上手就写视图而是先理解一个请求从浏览器出发到你屏幕上这段路是怎么走的。URL路由表分一杯羹然后视图函数处理逻辑然后模板渲染HTML三步缺一不可。这个链路你能默写出来后接下来再写真实业务就会有清晰的地图感。3. 灵魂三件套Model、View、Template是怎么配合的现在到了Django最核心的部分——Model、View、Template的协同工作。我见过不少新手被这三者绕晕一个常见的误区是光顾着学某一个比如疯狂折腾模板语法却不知道视图怎么把数据塞给模板或者深刻理解了模型但不会用视图组织逻辑。其实你只要跟着一个完整的小例子走一遍这个心结就解开了。我们以做一个产品列表页面为例就是把数据库里的商品名和价格展示到网页上。3.1 Model定义数据结构打开products/models.py定义一个最简的商品模型from django.db import models class Product(models.Model): name models.CharField(max_length100) price models.DecimalField(max_digits10, decimal_places2) created_at models.DateTimeField(auto_now_addTrue) def __str__(self): return self.name这里每一行都在向Django描述商品长得什么样。name是字符串、最长为100字符price是十进制数最多10位数字、其中2位是小数created_at是创建时间插入数据时自动填入。这就是ORM的用法——你用Python类来定义数据结构Django负责把它翻译成创建数据库表的SQL语句。定义完模型后需要生成并执行数据库迁移让数据库真的把这张表建出来python manage.py makemigrations products python manage.py migratemakemigrations生成迁移文件记录你对模型的改动migrate把改动真正应用到数据库。这是Django新手最容易含糊的一步——改完models.py不跑迁移然后SQL里查不到数据一直报错。记住这个命令组合就是改模型必迁移。如果你想看看Django生成了什么SQL语句可以用python manage.py sqlmigrate products 0001这能让你直观地看到ORM替你写了什么。对一个想搞懂ORM到底是怎么工作的的人来说这是一条捷径。3.2 View写业务逻辑的控制中枢模型定义好以后轮到写视图。Django有两种写法函数视图和类视图新手先从函数视图入手最直观。打开products/views.pyfrom django.shortcuts import render from .models import Product def product_list(request): products Product.objects.all() return render(request, products/product_list.html, {products: products})这个函数做了两件事第一用Product.objects.all()从数据库把商品数据全捞出来第二把捞出来的数据通过render函数交给模板渲染并把它作为HTTP响应返回给浏览器。注意render的第三个参数是一个字典它的作用是为模板提供数据——键是模板里用来引用的变量名值是要传给模板的Python对象。然后去项目下的urls.py配置路由把URL和视图函数对上from django.contrib import admin from django.urls import path from products import views urlpatterns [ path(admin/, admin.site.urls), path(products/, views.product_list, nameproduct_list), ]path(products/, views.product_list)的意思是当用户访问/products/这个地址时执行product_list这个函数。3.3 Template把数据渲染成好看的页面最后一步模板。在products应用下新建templates/products/目录创建product_list.html文件!DOCTYPE html html head title商品列表/title /head body h1在售商品/h1 ul {% for product in products %} li{{ product.name }} - ¥{{ product.price }}/li {% endfor %} /ul /body /html刷新http://127.0.0.1:8000/products/如果数据库里暂时没有商品页面上就是空列表。你可以在Django shell里手动插入两条数据试试python manage.py shell进入交互式环境后from products.models import Product Product.objects.create(name机械键盘, price299.00) Product.objects.create(name人体工学椅, price1299.00)再次刷新页面两条商品信息就会出现在列表里。走到这一步你已经完整走通了MTV三件套的协作流程Model定义数据View从数据库取出数据Template把数据渲染成页面。4. 数据操作实战以删除对象为引把ORM的常用操作一次讲透数据操作是Web开发的重头戏热搜词里常年挂着django执行查询-删除对象原因很简单会用ORM查数据、删数据才算真正迈过了Django的门槛。这一节我结合一个高频场景把ORM的创建、查询、修改、删除全套操作过一遍顺便把几个容易踩坑的细节讲透。还是用products应用里的Product模型举例。我先给你一个命令速查表后面再逐个展开。操作类型ORM写法说明创建一条记录Product.objects.create(name咖啡, price15.00)插入一条数据查询所有记录Product.objects.all()返回QuerySet按条件过滤Product.objects.filter(name咖啡)返回符合条件的QuerySet获取单条记录Product.objects.get(id1)查不到或查到多条会报错更新记录product.price 18.00; product.save()先查出对象改字段再保存删除记录product.delete()返回被删记录数和具体对象信息4.1 创建两种写法的区别创建对象有两种经典写法效果一样但使用场景不同# 写法一create一步到位 Product.objects.create(name散热支架, price99.00) # 写法二先实例化再save可以在保存前做更多字段处理 p Product(name显示器, price899.00) p.full_clean() # 可选校验字段合法性 p.save()实战中如果只是简单插入我倾向于用create如果插入前需要对字段做一堆清洗、默认值处理就先用实例化再save。顺带提一句Product.objects.all()返回的类型叫QuerySet这是个非常核心的概念——它本质上是一组数据库查询的集合而且具有惰性。什么意思当你写Product.objects.filter(price__gt100)时查询并没有立刻执行只有当你真正去遍历它、把它转成列表、调用len()之类操作时Django才会真正向数据库发SQL。这种设计能让ORM在组合多层过滤条件时变得高效避免中间产生大量无用查询。新手不用深究优化层面只要知道QuerySet是懒的这一点后面理解代码行为才不会懵。4.2 查询filter和get的边界新手最容易翻车查询是日常开发里最频繁的操作。Product.objects.filter(name咖啡)返回的是一个QuerySet可能包含0条、1条或多条数据Product.objects.get(name咖啡)则要求精确匹配且唯一如果查不到任何数据会抛Product.DoesNotExist异常查到了两条或更多会抛Product.MultipleObjectsReturned异常。所以get一般用于按主键查单条记录比如Product.objects.get(id3)用filter来应对可能存在多条数据的场景更安全。还有一个很实用的细节filter的条件用的是双下划线语法。比如price__gt100表示价格大于100name__icontains咖啡表示名称包含咖啡且不区分大小写created_at__date2024-05-20表示按日期过滤。这套语法是Django ORM的精华熟练掌握后查数据会非常顺手。我先上两个实际例子# 查询价格大于100的Commits商品 expensive Product.objects.filter(price__gt100) # 查询名称里包含支架的商品 stands Product.objects.filter(name__icontains支架)4.3 更新与删除delete()的返回值里有文章更新操作的核心是先取对象改字段再save。值得注意的是如果你用filter拿到的是一整个QuerySet可以批量更新Product.objects.filter(price__gt500).update(price499.00)一条SQL就把所有高价商品价格改成499这在效率上比循环save强太多。删除操作是这个热搜词的主角。删一条数据的写法是product Product.objects.get(id1) product.delete()值得留意的是delete()的返回值非常有信息量。它返回一个(total_deleted, {模型名: 数量})这样的元组。比如(1, {products.Product: 1})第一个数字是总共删掉了多少条记录第二个字典则明细列出每个模型删了多少条。为什么会有多个模型呢因为Django默认在模型外键关系上做级联删除——你删一个商品分类该分类下的所有商品都给删了如果你开启了on_deletemodels.PROTECT之类的保护式外键删除行为又会不同。所以删数据之前务必想清楚级联效应这是很多线上事故的根源。还有一个批量删除的坑对QuerySet直接调delete()是批量删除如Product.objects.filter(price__lt10).delete()它会删除所有满足条件的数据且不会逐一调用每个对象上的任何删除逻辑。慎用最好先select一条出来看看条件是否符合预期。4.4 在真实页面里组合这些操作光在shell里操作刷成就感很多人还是不知道要在哪写这些代码。我给你一个非常实用的示例在视图里把删除商品做成一个带确认的跳转。from django.shortcuts import get_object_or_404, redirect def product_delete(request, product_id): product get_object_or_404(Product, idproduct_id) if request.method POST: product.delete() return redirect(product_list) return render(request, products/product_confirm_delete.html, {product: product})然后在urls.py加一条路由path(products/int:product_id/delete/, views.product_delete, nameproduct_delete),int:product_id是Django路由里的路径参数它会把URL里的数字自动转换成整数传给视图函数。这样你的列表页里每个商品后面放一个删除按钮点击后先到确认页POST确认后真正删除再跳回列表。这套流程就是Django开发里最基础的CRUD闭环。等你熟练了这套操作再去用Django视图类的CreateView、DeleteView会发现那只是把这里的逻辑封装成了更高层的方法集成。5. 真实开发中的Django它在企业级项目里该站哪班岗聊完技术细节我必须把视角拉高一点。你学了Django的基础增删改查、跑通了MTV流程但这距离用它做一个企业级项目还有一段认知上的距离。这一节我聊些我在项目里踩过、看别人踩过之后的体会。先明确一点Django在企业级Python项目里最常见的职责有两个——做业务管理后台和做Web API后端。尤其是Python Web企业级项目开发教程这个搜索词背后隐含的需求其实不是再学一遍基础语法而是我该怎么把一个正经的业务系统拆成模块化设计。Django的Admin后台功能本身就是企业标配你只要把模型注册进admin.py一套包含增删改查、筛选、权限控制的后台界面就出来了。这个做内部运营工具能帮你省下好几个月工期。它的用法如下# products/admin.py from django.contrib import admin from .models import Product admin.site.register(Product)创建超级用户并启动服务器后访问http://127.0.0.1:8000/admin/后台界面直接可用。以前我给一个传统企业做库存管理系统就是靠Django Admin先在三天内上线了内测版再逐步根据业务需求定制自己的管理页面。再说API后端。现在的前后端分离开发大行其道如果你用Django只做后端通常不会直接返回HTML页面而是返回JSON数据。这时候你会用到Django REST frameworkDRF——它基于Django专门用来快速构建RESTful API。DRF的序列化器Serializer、认证机制、视图集ViewSet能大幅简化API的开发过程。一个简单的例子from rest_framework import serializers, viewsets from .models import Product class ProductSerializer(serializers.ModelSerializer): class Meta: model Product fields __all__ class ProductViewSet(viewsets.ModelViewSet): queryset Product.objects.all() serializer_class ProductSerializer配上路由注册一个支持增删改查的完整API接口几十行代码就能搞定。这是Django在企业级市场经久不衰的核心原因从Model定义到接口暴露节奏非常顺滑。5.1 Django不太适合的舞台虽然我把Django夸得挺多但它的边界也得讲清楚不然你会在错误的地方用了它。Django的请求处理模型偏传统每来一个请求就把它放进一个同步的请求-响应周期里长连接、高并发的实时推送类场景比如聊天系统、实时协作白板、海量物联网数据流不是它的主战场。这种活儿通常会交给异步框架如FastAPI、Tornado或者单独用消息队列与专用服务来处理Django则负责它擅长的业务管理、数据持久化和接口编排。还有个常见的误区是Django单体化撑不起大流量。其实单体的Django配合Celery做异步任务、Redis做缓存、数据库读写分离把业务拆成模块化App它完全能扛住中等规模的并发访问。说白了大部分项目的瓶颈从来不在框架而是在SQL设计、缓存策略和部署架构上。先别一上来就微服务系统还没烧起来拆分倒是把自己先拆晕了。5.2 用AI辅助写Django代码这件事该怎么看热搜词里有一个用ai agent开发django我在这儿多说两句。现在AI辅助编程确实已经进入不少团队的日常AI能帮你快速生成CRUD代码、补全配置文件、甚至根据自然语言描述出来一整个Django App的雏形。我自己也用确实能提速尤其适合那些模式化很强的代码。但这里有个残酷真相**AI生成的代码质量取决于你对Django本身的理解深度。**如果你搞不懂QuerySet惰性、搞不清模型迁移、看不懂DRF的序列化流程AI生成的代码出bug时你连错误提示都读不懂更别提修复了。所以对新手的建议很明确初期一定要手工把基础链路写烂写熟把Django的原理和内功练好再把AI当加速器用它突然会变得很好用。6. 新手最常踩的坑和我给你的学习路线最后这部分我把这些年我在各种群聊里看到的新手高频错误总结成一张表每一个我都亲身踩过或者看过别人流着泪爬出来常见坑错误现象正确做法忘了跑迁移表不存在、字段报错每次改模型后执行makemigrationsmigrate忘了注册App模板找不到、URL报错settings.py的INSTALLED_APPS加入App名称settings.py的DEBUG部署后被用户看到隐私报错上线必须设为DEBUGFalse并用正规服务器跑时区问题时间显示和本地差几个小时setting里的USE_TZFalse或正确配置TIME_ZONE模板语法错误页面空白或传来传去全是{}先print传进render的上下文再检查模板变量名静态文件404CSS、JS都加载不出来开发阶段配置STATICFILES_DIRS并确认模板用{% load static %}代码一股脑堆在views.py一个文件几千行维护噩梦按App/service划分逻辑把可复用的业务抽成单独模块这些坑有个共同点几乎都不是不会写而是不知道流程。“不知道流程”这个事儿真得靠大量的实际项目来补课——你光看教程、光读官方文档永远没法建立肌肉记忆一旦换到新环境还是会懵。我的建议是啃透一个真实的完整项目哪怕是从零开始做一个简单的博客系统也一定要亲自经历从建项目、建App、写模型、跑迁移、写视图、套模板、接Admin、部署上线的全过程。这个过程走完一遍Django的骨架才算焊进了你的技能树里。接下来你可以按这个顺序进阶先熟练函数视图和QuerySet然后学DRF做API再学Django的高级特性信号、Celery异步任务、缓存、权限系统每一步都跟着项目走而不是跟着文档走。学习资料方面官方文档仍然是最好的选择——虽然它的英文文档读起来有些枯燥但精确、全面。再搭配一两本实战书就足够不需要囤教程。还记得去年有个学员跑来找我说他囤了十几个小时的视频课听的时候神清气爽一动手就废。这太正常了编程这东西听懂了和会写了之间隔着几百次报错的距离。最后分享一个我自己的小习惯每学一个新框架我都会准备一个万能Demo项目。这个项目麻雀虽小五脏俱全包含了认证、增删改查、权限、API这些常见模块技术更新后我会随手把它维护一下。有了它我接任何新项目都能快速起步也方便对比不同版本的API差异。技术圈总说Django老了可它依然是Python Web世界里迭代得最稳、生态最全的选择之一。框架的好坏其实没那么重要重要的是你自己能不能把一个想法顺着它给出的轨道干净利落地变成能跑的东西。希望这篇内容能帮你少走些弯路。