ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Django基础入门教程:从MTV架构到第一个实战项目

Django基础入门教程:从MTV架构到第一个实战项目

我是个写过好几年 Django 的老开发了,每次有人问“Django 怎么入门”,我都不想直接甩官方文档——那玩意对新手太不友好,翻两页就困了。所以这篇“Django 基础入门教程(第一篇)”没有废话,不堆概念,用一次完整的建站流程,把 Django 最核心的东西串起来。这篇能帮你回答三个问题:Django 到底是什么、它凭什么这么流行、以及我该怎么把第一个项目跑起来。就算你只是刚学完 Python 语法、还没碰过任何 Web 框架,跟着这篇走一遍,也能亲手做出一个带数据库后台的小网站。

1. 为什么是 Django:框架定位与核心设计

1.1 它解决什么问题

写网页最枯燥的部分其实不是业务逻辑,而是那些“每个网站都有的破事”:用户提交表单、登录验证、数据库读写、后台管理、防止黑客攻击。你要是每次都用原生 Python 重写一遍,写完基本就废了,而且安全性还没保障。Django 最大的价值就是把这一整套通用能力打包好,让你专注写真正属于项目的部分。

很多人一上来就纠结“Django 好还是 Flask 好”,这种问题问早了。Flask 更像一把手工刀,灵活但没有太多内置装备,什么都得自己拼;Django 更像一个精装工具箱,里面头盔、护具、常用工具全齐了。对刚起步的人来说,先学会用一套完整的工具干活,比什么都自己造更有效率。

我见过不少只用 Flask 写了两年的人,连表单校验都还在手写正则,到了 Django 这边发现全是现成的——这差距不是能力问题,是框架的设计理念完全不同。Django 走的是“batteries included”(电池全家桶)路线,官方自己维护 ORM、模板引擎、后台管理、认证系统,生态非常统一。

1.2 核心组件与一次请求的完整旅程

Django 常被人说是 MTV 架构(Model-Template-View),这和传统的 MVC 有点区别,但核心思想一样,都是分层解耦。我刚学的时候觉得这术语唬人,其实拆开看非常简单:

  • Model:负责和数据打交道。你在 Python 里定义一个类,Django 的 ORM 帮你把它映射成数据库表,不用自己写 SQL。
  • Template:负责页面长什么样,决定用户能看到什么 HTML。
  • View:负责业务逻辑——用户想干嘛,数据该怎么取,最后把结果传给哪个模板。

一次完整的请求,流程大致是这样:

  1. 用户在浏览器访问一个 URL,比如http://127.0.0.1:8000/articles/
  2. Django 拿着路径去 URL 路由表里找匹配规则
  3. 匹配到后,把请求转交给对应的视图函数(View)
  4. 视图函数处理逻辑,通常要查询数据库(Model)
  5. 结果数据塞给模板(Template),模板渲染出 HTML
  6. 最后把 HTML 作为响应传回浏览器

这六步就是 Django 的“心法”,后面写多少代码都绕不开这个流程。我建议你把这六行抄下来贴在显示器边上,遇到卡壳就对着它想“现在跑到第几步了”。

1.3 认识你的工作目录结构

Django 用命令行工具创建项目后,会生成一个固定的骨架。第一次看到这堆文件的人都会懵,我当初也懵了,但其实每个文件职责非常明确。

文件作用重要程度
manage.py项目总指挥,几乎所有命令都要通过它执行必需
settings.py全局配置:数据库、安装的应用、时区、模板位置等必改
urls.py路由入口,前端请求从这里开始分发必改
wsgi.py/asgi.py部署时用,本地开发基本不用碰了解
db.sqlite3本地数据库文件,第一次迁移后自动生成自动

先把这几个文件弄明白,项目的骨架就吃透了。后添加的每个“应用”也会有自己的models.py、views.py、urls.py,但manage.py只管全局。

2. 环境搭建与第一个项目:从零跑通

2.1 Python 环境与虚拟环境

Django 是 Python 的第三方库,装它之前先确认你的 Python 版本。当前主流版本是 3.8 到 3.12,不建议用太旧的版本,因为新版本 Django 已经放弃老 Python 了。装之前可以先看下官方支持的组合,省得后面报一些莫名其妙的环境错误。

强烈建议在虚拟环境里安装。虚拟环境相当于给每个项目单独隔一个小房间,里面放的 Python 包互相不干扰。你以后会同时维护多个项目,很可能这个项目要 Django 4.2、那个要 Django 5.0,没有虚拟环境的话,版本冲突会把你折磨到怀疑人生。命令行里这样建:

# 创建虚拟环境(venv 是 Python 自带工具,不用额外装) python3 -m venv myenv # 激活它 # Windows 环境执行: myenv\Scripts\activate # Mac / Linux 环境执行: source myenv/bin/activate

激活之后,终端提示符前面会出现(myenv)的字样,看到它就说明当前已经在虚拟环境里了。然后安装 Django 就非常简单:

pip install django # 验证一下 django-admin --version

如果这行能输出版本号,环境就没问题了。新手最容易犯的错误是:建了虚拟环境但忘了激活,直接pip install django,结果装到了全局环境里,导致启动项目时提示找不到模块。这事我犯过不止一次,先看一眼命令前的(myenv)再执行,能省很多事。

2.2 创建项目和应用的完整命令

Django 的概念里,**项目(project)和应用(app)**是两回事。项目是整个网站容器,应用是里面一个个功能模块,比如一个博客系统可以有文章应用、评论应用、用户应用。第一次建,没必要把概念背得多熟,先这样想:项目是房间,应用是房间里不同的家具区。

创建项目:

# 在当前目录下创建一个名叫 myblog 的项目 django-admin startproject myblog

这个命令会生成上一节说的那个骨架。然后进入项目目录,再创建一个应用:

cd myblog python manage.py startapp articles

创建完应用后,有一个极其关键的步骤:到settings.py里的INSTALLED_APPS列表中,把你的应用加进去。不这么做的话,Django 根本不知道你创建了这个应用,后面数据库迁移会永远找不到你的表。

INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', # ... 其他默认应用 'articles', # 加上这一行 ]

2.3 第一次启动项目时的常见报错

配置好之后,运行:

python manage.py runserver

如果看到Starting development server at http://127.0.0.1:8000/,恭喜你,项目已经活了。这时在浏览器打开http://127.0.0.1:8000/,会看到 Django 默认的火箭欢迎页。

这个阶段容易踩的问题我整理一下:

  • 端口被占用:提示address already in use。要么换端口,比如python manage.py runserver 8080,要么把占用端口的进程杀掉。
  • 提示 No module named 'django':几乎都是虚拟环境没激活或装错环境,用pip list看看 django 在不在。
  • 改了代码但页面没变化:runserver 自带自动重载,但新增文件的部分情况不会自动生效,重启一下就好。

Django 的开发服务器有一个好处,它会实时检测代码变化并自动重启,这在本地开发时非常爽,改完代码刷新页面就行,不用手动重启。

3. 核心概念逐个拆解:URL、视图、ORM、模板

3.1 URL 路由:入口控制

URL 路由是 Web 框架的交通警察。用户请求http://127.0.0.1:8000/articles/时,这个路径会先进项目的urls.py,Django 从上到下按顺序匹配规则,碰到第一个能匹配的就用对应的视图。

最基本的写法是path():

# myblog/urls.py from django.urls import path from articles import views urlpatterns = [ path('articles/', views.article_list, name='article_list'), path('articles/<int:pk>/', views.article_detail, name='article_detail'), ]

这里<int:pk>是动态参数,意思是这个位置接受一个整数,并把它作为参数传给视图函数。除了int,常用的转换器还有str(字符串)、slug(适合文章标题型短横线字符串)。这种写法比老一代的正则url()直观多了,推荐新项目统一用path()。

name='article_list'也很关键。你以后在模板里引用 URL 时,靠的是这个名字而不是硬编码路径。比如href="{% url 'article_list' %}",这样不管路径怎么改,只要 name 不变,模板里的链接都不会断。

初学者容易犯的错是把业务路由都堆在项目根urls.py里。正确的组织方式是按应用拆分:每个应用一个自己的urls.py,再在主路由里用include()挂进来:

# myblog/urls.py from django.urls import include, path urlpatterns = [ path('articles/', include('articles.urls')), ]

这样文章相关的路由都在articles/urls.py里维护,各管各的,项目一大了优势马上体现。

3.2 视图层:请求与响应

视图是 Django 里最核心的代码块。一个最简单的函数视图长这样:

# articles/views.py from django.http import HttpResponse def article_list(request): return HttpResponse("这里是文章列表")

这里面的request参数携带了用户请求的所有信息:请求方法(GET/POST)、用户是否登录、提交的表单数据、请求头里的各种信息。你可以在视图里通过request.method判断请求方式,通过request.GET.get('param')拿查询参数。

实际项目里,视图直接返回HttpResponse("字符串")的机会不多,更多是返回渲染后的 HTML 模板,或者给前端接口返回 JSON:

from django.shortcuts import render from django.http import JsonResponse def article_list(request): # 假设这里用 ORM 查询到了文章数据 articles = [...] if request.path.endswith('json'): return JsonResponse({'data': articles}) return render(request, 'articles/list.html', {'articles': articles})

render的第三个参数是个字典,这字典就是给模板用的上下文,模板里怎么调用待会儿说。从新手角度,视图层需要掌握的套路就两条:从request里取参数、用render渲染模板,其他的装饰器、类视图等后面再慢慢进阶。

3.3 ORM 与模型:不写 SQL 的数据库操作

ORM(对象关系映射)是 Django 最值得吹的地方之一。你在 Python 里定义的这个类,就是一个数据库表:

# articles/models.py from django.db import models class Article(models.Model): title = models.CharField(max_length=200) content = models.TextField() created_at = models.DateTimeField(auto_now_add=True) def __str__(self): return self.title

CharField对应数据库的 varchar,TextField对应 text,DateTimeField对应 datetime。Django 会根据这些字段类型自动生成建表 SQL。你不需要关心底层是 MySQL 还是 SQLite,框架帮你做了抽象。

写完之后,关键操作是生成迁移文件并执行迁移:

python manage.py makemigrations python manage.py migrate

第一个命令是问你“检测到模型变化,生成一个迁移计划”,第二个是真正“把这计划执行到数据库”。这俩顺序不能乱。新手最常犯的错是改了models.py却不重新执行这两个命令,结果页面报错说没有这个表。

查询数据的语法很直观:

# 查所有 Article.objects.all() # 过滤条件 Article.objects.filter(title__contains='Django') # 取单个 Article.objects.get(id=1)

注意objects.all()返回的并不是数据库里真实的数据列表,而是一个 QuerySet(懒查询对象),真正访问数据库的时机是遍历它或者调用.first()、.count()这类方法时。这个设计是为了能多级链式过滤,性能更好,但新手容易产生“我明明查了为什么没数据”的错觉——先打印一下再判断。

4. 一个能跑的最小 Demo:完成一次数据库读写闭环

4.1 定义模型并注册后台

光讲概念没有用,这里我带你做一个真正能跑的最小 Demo:一个带后台管理的文章列表页。项目名就叫myblog,应用名articles,已经按上一节的步骤创建好了。

先在articles/models.py里定义文章模型,字段用上面写过的那个Article即可。核心是别忘了给模型加一个_str_方法,不然后台里所有文章都显示成“Article object (1)”,你根本分不清谁是谁。

然后需要把模型注册到 Django 自带的 Admin 后台。打开articles/admin.py:

# articles/admin.py from django.contrib import admin from .models import Article @admin.register(Article) class ArticleAdmin(admin.ModelAdmin): list_display = ('title', 'created_at') search_fields = ('title', 'content')

list_display控制后台列表页显示哪些列,search_fields提供搜索框。这两项是刚需配置,不加的话后台只有显示默认字段,用起来很不顺手。

4.2 使用系统自带后台

执行完数据库迁移后,需要创建管理员账号:

python manage.py createsuperuser

按提示填用户名、邮箱(可空)、密码。注意密码输入时不显示字符,这是正常现象,不是键盘坏了。然后启动服务,访问http://127.0.0.1:8000/admin/,用刚创建的账号登录。

这里就是 Django 最让人“哇”的地方——一个带增删改查、分页、过滤、权限控制的完整后台系统,一行业务代码都没写,全是框架送的。你可以在后台点几下,新增几篇文章试试手感。这也是我说新手入门不要第一步就选 Flask 的原因之一:Django 把管理后台送给你,刚起步就有了可视化操作,自信心瞬间上来。

4.3 写视图、配路由、做模板

后台里有数据了,下一步是写一个公开的文章列表页。

先在articles/views.py里写视图:

# articles/views.py from django.shortcuts import render from .models import Article def article_list(request): articles = Article.objects.all().order_by('-created_at') return render(request, 'articles/list.html', {'articles': articles})

order_by('-created_at')表示按创建时间倒序,-号是降序。这一步已经把数据库里的文章都取出来了,接下来只要交给模板。

在应用目录下建templates/articles/list.html,注意模板目录结构不能随意,Django 是按应用名/templates/应用名/模板文件的路径约定查找的,应用名这层必须保留,防止多个应用有同名模板时覆盖。

模板内容:

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>文章列表</title> </head> <body> <h1>最新文章</h1> {% for article in articles %} <h2>{{ article.title }}</h2> <p>{{ article.created_at }}</p> <p>{{ article.content|truncatechars:50 }}</p> <hr> {% empty %} <p>还没有文章,去后台添加一篇吧。</p> {% endfor %} </body> </html>

{% for %}是模板循环语法,{{ }}是变量输出,{{ article.content|truncatechars:50 }}里的管道符是过滤器,作用是把超长文本截断到 50 个字符。{% empty %}是数据列表为空时的兜底文案,这个细节很贴心,列表页不至于白花花一片。

最后把路由连起来,在articles/urls.py里添加:

# articles/urls.py from django.urls import path from . import views urlpatterns = [ path('', views.article_list, name='article_list'), ]

再去项目根myblog/urls.py里 include 一下:

# myblog/urls.py from django.urls import include, path urlpatterns = [ path('admin/', admin.site.urls), path('articles/', include('articles.urls')), ]

访问http://127.0.0.1:8000/articles/,你就能看到后台添加的文章全部展示在页面上了。到这里,一条完整的链路已经打通:后台写数据、ORM 读数据、模板展示数据、URL 控制入口。别看这个小页面不起眼,它涵盖了 Django 核心的八成内容。

5. 新手最容易踩的坑与排查实录

5.1 环境与启动类问题速查

现象大概率原因解决办法
No module named 'django'虚拟环境没激活或装错环境检查命令前是否有(myenv),在正确的环境里pip install django
ImproperlyConfigured: ...settings.py 里有语法错误或引用了不存在的模块对照报错行号检查 settings
启动后页面 200 但样式全没开发环境没配静态文件,部署时才常见本地一般不影响功能,先忽略
port 8000 already in use端口占用runserver 8080换端口,或杀进程
改了models.py但表没变没执行 makemigrations/migrate按顺序跑这两个命令

这里额外提醒一个很容易被忽略的问题:Windows 上使用虚拟环境时,偶尔会遇到执行activate被禁止执行的策略报错,一般用激活脚本路径直接调用或者换 PowerShell 的 ExecutionPolicy 就能解决,但这和治疗代码无关,遇到时知道是环境权限问题就行。

5.2 迁移与数据库的坑

Django 的迁移系统设计得已经很自动了,但有几个常见操作误区值得单独说。

第一,不要在没备份的情况下直接删迁移文件。有些人看到迁移文件越堆越多就手痒,直接删掉整个migrations目录下的文件,然后重新makemigrations,如果数据库里的迁移记录和文件对不上,等着你的就是各种莫名其妙的表结构错误。正确做法是保留迁移文件,真有特殊情况再查文档重置。

第二,改了models.py的字段类型或加字段后,要立刻重新生成迁移并执行。很多新手的流程是“改模型 → 刷新页面 → 报错了 → 再执行迁移”,完全可以把顺序反过来,每次改完模型先跑命令再调试。

第三,查询时小心 N+1 问题。当一对多关系查询时,光用objects.all()会先查一次主表,然后每遍历一条数据又各查一次关联表,100 条数据就会发出 101 条 SQL。解决方式是用select_related(适合外键)或prefetch_related(适合多对多/反向关系)一次性把关联数据查出来。新手阶段可能感觉不到性能差异,数据量一上来,这地方就是性能瓶颈。

5.3 配置文件里的安全细节

开发阶段为了省事,很多人会把settings.py里的DEBUG一直保留为True,这本身没问题。但如果你把DEBUG=True的项目直接丢到线上,那等于把自己的代码路径、配置信息、甚至数据库连接信息都暴露给访问者了。真正上线前至少要做三件事:

  1. DEBUG设为False
  2. ALLOWED_HOSTS里填上你的真实域名或 IP,空或*都是有风险的状态
  3. 换掉默认的SECRET_KEY,这串字符是密码学签名的核心,泄露了会被人伪造 session

这些细节第一篇文章不展开,但你先知道有这回事,后面深入时就不会一脸懵。

6. 一点个人建议

第一篇教程到这里,主线内容已经讲完了。最后分享几个我实操中觉得很有用的习惯。

第一,新建项目后不要急着写业务代码,先跑一遍runserver+createsuperuser,确认环境和后台都正常,然后再开始加应用。这样每一步的“地基”都是稳的,后面排查问题时能快速缩小范围。

第二,写视图和模板时多用 Django 自带的开发服务器实际测试,别光在代码里埋头推演。打开浏览器点一点,用 DevTools 看看请求是否正确返回,比事后猜哪里错了高效得多。

第三,一定养成看报错日志的习惯。Django 的报错页是我用过的框架里最友好的,页面顶部会直接告诉你异常类型、触发位置、关键代码上下文。很多人遇到红屏第一反应是截图问人,其实自己读一遍最后几行,大多数问题当场就能解决。

这篇“Django 基础入门教程(第一篇)”先把 MTV 骨架和完整链路跑通,后面第二篇可以深入讲模板继承、表单处理和用户认证。如果你想学的方向是写 API,也可以把 ORM 和视图这块吃透后直接转 DRF(Django REST Framework),路线都是通的。记住一个原则:不要追求把概念背熟才开始动手,先跑起来,边做边理解,这才是入门 Django 最快的方式。

返回列表