ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Django Web开发实战:从环境搭建到博客系统完整教程

Django Web开发实战:从环境搭建到博客系统完整教程 1. 为什么是DjangoPython Web开发的第一选择1.1 从零开始认识Django框架先说个真实的感受。我做了这么多年的Python开发带过不少新人也见过很多人在Web框架的选择上纠结半天。有人觉得Flask轻量灵活有人觉得FastAPI性能好但如果你是想认认真真做一个完整的Web应用、想把精力花在业务逻辑而不是重复造轮子上Django绝对是最稳妥的选择。Django诞生于2003年最初是劳伦斯出版集团内部用来管理新闻内容的框架2005年开源发布。它的设计哲学是“batteries included”——直译过来就是“电池已包含”意思是框架本身已经帮你集成了Web开发中绝大多数常用的功能模块。你不需要像Flask那样自己去集成数据库ORM、表单处理、用户认证、Admin后台这些Django全部自带而且做得很完善。更直白一点说Django就像是一套精装修的房子你拎包入住就行。Flask则像是毛坯房你可以按自己的喜好装修但一切都要自己来。对于绝大多数项目Django的这套“精装修”能让你少走太多弯路。1.2 Django能做什么三个真实场景很多人对框架的理解停留在“能写网站”这个层面但实际上Django的覆盖面远不止于此。我随便举三个我实际接触过的场景内容管理平台。新闻网站、博客系统、企业官网这是Django最经典的适用场景。借助自带的Admin后台非技术人员也能方便地管理文章、图片、分类。我做过的企业官网项目运营人员每天自己更新新闻和产品信息完全不需要开发介入。数据处理与可视化平台。Django配合Pandas、ECharts可以做数据分析和可视化展示平台。上传Excel文件后台完成数据清洗和分析前端用图表展示结果。这类“内部数据工具”在中小企业里需求非常大而Django的ORM和模板系统让这类项目开发效率极高。电商与业务系统。虽然国内电商用Java居多但Django做中小型电商系统、订餐系统、预约系统也非常成熟。自带的用户认证、Session管理、CSRF防护让你不用从零考虑安全问题Django的文档里甚至有一整章讲如何保证部署安全。所以说Django不是只能做博客的玩具框架它是真正能支撑起商业项目的成熟框架。1.3 谁适合学Django目标人群画像根据我的经验下面这几类人最适合从Django入手学习Web开发第一类是已经有Python基础但没接触过Web开发的人。你写过爬虫、做过数据分析但打开浏览器输入网址背后的逻辑对你来说是个黑盒。Django能让你很快建立起“请求-处理-响应”的完整认知。第二类是计算机相关专业的学生。课程作业、毕业设计、实验室项目Django是出成果最快的框架。我一个学生用Django两周做了一个社团管理网站从数据库设计到前端页面全部搞定。第三类是想快速验证产品想法的人。如果你有一个创业点子想快速做出MVP去测试市场Django的全家桶特性让你不用在基础设施上浪费时间专心打磨业务逻辑。2. 环境准备Python与Django的安装搭配2.1 Python版本选择与安装细节先说结论目前推荐使用Python 3.10-3.12版本。原因很简单Django 4.x和5.x版本对Python版本有明确要求Django 5.0需要Python 3.10以上。选一个不太新也不太旧的Python版本生态兼容性最好各种第三方库基本都跟得上。具体安装步骤我不赘述网上教程一大把。我只说三个容易踩坑的细节第一务必勾选“Add Python to PATH”。安装时这个选项默认不勾选很多新手装完Python之后在命令行敲python提示找不到命令十有八九就是这一步没勾。如果已经装完但没勾选可以手动把Python安装目录和Scripts目录加到环境变量里。第二用python -m pip而不是直接敲pip。Windows系统上直接敲pip经常会出现“pip不是内部或外部命令”的报错这是因为pip的路径没配置好。用python -m pip install这种方式相当于明确指定用当前Python解释器去运行pip模块能规避很多路径问题。第三建议用虚拟环境venv。Django项目依赖的第三方库版本和系统里其他项目可能冲突。虚拟环境相当于给每个项目一个独立的小房间里面装什么库都不影响外面。创建的命令很简单python -m venv myenv创建好之后Windows系统激活方式是myenv\Scripts\activateMac和Linux系统激活方式是source myenv/bin/activate激活之后命令行前面会出现(myenv)字样说明你已经进入虚拟环境了。2.2 安装Django版本选择与验证在虚拟环境激活的状态下安装Django就很轻松了pip install django默认会安装最新稳定版本。如果你想安装指定版本比如3.2 LTS版本pip install django3.2.25这里科普一下Django的版本策略。Django的版本号是X.Y.Z格式X是主版本号Y是次版本号Z是补丁版本号。官方会为部分版本提供长期支持LTS通常LTS版本维护周期长达3年以上而普通版本只有8个月的维护期。如果是商业项目强烈建议用LTS版本因为安全更新跟得上不用频繁升级。Django 3.2是LTS版本Django 4.2也是LTS版本Django 5.0不是LTS。我的建议是新项目用4.2 LTS稳妥且功能足够。安装完之后验证是否成功的命令python -m django --version能显示出版本号就说明Django装好了。如果报错“No module named django”大概率是你没有激活虚拟环境或者激活了但不能确认。提示Django开发中涉及的依赖安装失败九成以上是网络问题或Python版本不兼容问题。网络问题可以换国内镜像源比如pip install django -i https://pypi.tuna.tsinghua.edu.cn/simple。2.3 开发工具推荐编辑器与调试神器工欲善其事必先利其器。Django开发我推荐下面几个工具主推PyCharm。JetBrains出品的Python IDE专业版直接内置Django支持包括模板文件的高亮、ORM模型的代码提示、一键运行Django项目。社区版虽然不内置Django专业支持但当作普通Python编辑器也完全够用。备选VS Code。如果你不想用笨重的PyCharmVS Code加上Python扩展和Django模板扩展也能获得不错的体验。轻量、启动快、插件丰富是它的优势。对于Django的模板文件中{% %}语法的高亮需要安装“Django”这个扩展插件。调试神器django-debug-toolbar。这个第三方库能在页面侧边栏展示SQL查询次数、请求耗时、缓存命中等信息是排查性能问题的利器。安装和启用非常简单pip install django-debug-toolbar然后在settings.py的INSTALLED_APPS中加入debug_toolbar在urls.py中加入对应的路由即可。它的价值在你项目数据量上来之后会体现得非常明显。3. 第一个Django项目从创建到运行3.1 创建项目的两种方式在虚拟环境激活状态下找一个你用来存放代码的目录执行django-admin startproject myproject这里的myproject是你的项目名称。执行完你会发现生成了一个文件夹里面的结构大概是这样myproject/ manage.py myproject/ __init__.py settings.py urls.py asgi.py wsgi.py解释一下各文件的作用。最外层的myproject是项目的容器目录名字随便取。manage.py是Django项目的管理脚本以后启动服务、创建应用、执行数据库迁移都要靠它。内层的myproject是Python包settings.py是整个项目的配置文件urls.py是根路由配置wsgi.py和asgi.py是部署Web服务器时用到的入口文件。还有第二种创建方式用django-admin startproject myproject .注意最后面有个点表示在当前目录下创建项目不会多套一层文件夹。这个方式在后续部署到服务器时会用到具体区别在后文部署部分说。3.2 启动开发服务器见证奇迹的时刻在myproject目录下执行python manage.py runserver看到类似这样的输出就说明启动成功了Watching for file changes with StatReloader Performing system checks... System check identified no issues (0 silenced). You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions. Run python manage.py migrate to apply them. Django version 4.2.7, using settings myproject.settings Starting development server at http://127.0.0.1:8000/ Quit the server with CTRL-BREAK.看到的那行“You have 18 unapplied migration(s)”提示不用慌张这是Django自带的admin、auth等应用需要初始化数据表。执行一下python manage.py migrate然后再刷新页面Django的默认欢迎页就出来了。这里说几个新手最容易遇到的问题。如果你在页面看到的是“DisallowedHost”错误说明你需要把域名或IP加到settings.py里的ALLOWED_HOSTS中。开发时改成ALLOWED_HOSTS [*]能解决大部分问题但生产环境为了安全不建议这么写。如果你启动runserver时指定了端口语法是python manage.py runserver 8080把默认的8000端口换成8080。如果指定IP语法是python manage.py runserver 0.0.0.0:8000这样局域网内其他设备也能通过你的IP访问。runserver是Django自带的开发服务器它的自动重载功能非常实用。你保存代码之后服务器会自动重启不用手动操作。但记住一个关键点这个服务器只适合开发调试千万别直接部署到线上。性能和安全都不过关。3.3 创建第一个应用Django里的“项目”和“应用”是两个不同的概念。项目是一个网站整体的配置和路由集合应用则是完成某个具体功能的模块。打个比方项目是一栋楼应用是楼里的各个房间——有厨房、有卧室、有卫生间每个房间功能独立组合起来就是一个完整的家。创建应用的命令python manage.py startapp blog这会在项目目录下生成一个blog文件夹里面的结构大概是blog/ __init__.py admin.py apps.py models.py tests.py views.py migrations/ __init__.py目前对这些文件不用全部理解只需要知道models.py是定义数据模型的地方views.py是写业务逻辑的地方admin.py是注册后台管理的地方。创建完应用之后记得在settings.py的INSTALLED_APPS列表里加入blog。这一步是初学者最容易漏掉的不加的话你会遇到很多诡异的错误——表建不了、模板加载不了、Admin里看不到这个应用。INSTALLED_APPS开头是INSTALLED_APPS [ django.contrib.admin, django.contrib.auth, django.contrib.contenttypes, django.contrib.sessions, django.contrib.messages, django.contrib.staticfiles, blog, ]记得在最后加上blog这一行。4. Django核心概念URL、视图与模型4.1 MTV架构MVT模式到底是怎么回事Django的架构模式叫MTV——Model、Template、View和传统的MVC有点关系又不完全一样。具体来说三个角色的分工是这样的Model模型负责和数据库打交道用Python类定义数据表结构对应MVC中的Model。Template模板负责页面呈现用HTML加上Django模板语言生成用户看到的界面对应MVC中的View。View视图负责业务逻辑接收请求、处理数据、返回响应对应MVC中的Controller。那URL配置在哪一步在Django里URL路由urls.py负责把用户请求的网址映射到对应的View函数。整个流程是用户访问一个网址 - urls.py找到对应的View函数 - View函数从Model取数据 - View把数据传给Template - Template渲染成HTML返回给用户。我用一个生活化的例子说明。你去餐厅吃饭URL就是菜单你点的菜名对应到后厨的单子View后厨去仓库拿食材Model厨师做好菜Template端到你面前。三者的配合就是这么个流程。4.2 写一个能用的视图函数在blog/views.py里写一个最简单的视图from django.http import HttpResponse def index(request): return HttpResponse(你好Django)然后在myproject/urls.py里配置路由from django.contrib import admin from django.urls import path from blog.views import index urlpatterns [ path(admin/, admin.site.urls), path(, index), ]这里有两个细节要解释一下。path(, index)表示当用户访问根路径也就是域名后面什么都不加时调用index函数。而path(hello/, index)则表示用户访问“/hello/”这个路径时才调用。此时如果你运行runserver并访问http://127.0.0.1:8000/页面上会显示“你好Django”。这算是最简陋的一个Web页面了但你从这行字开始已经真正走通了“用户请求-路由匹配-视图处理-返回响应”这条Web开发的核心链路。4.3 模型用Python类定义数据表Django最有价值的部分之一就是它的ORMObject-Relational Mapping对象关系映射。简单来说你用Python类定义数据表结构Django负责把这个类转换成数据库里的表。这一层转换让你完全不用写SQL语句而且未来切换数据库比如从SQLite切到MySQL也不需要修改业务代码。在blog/models.py里定义一个Article模型from django.db import models class Article(models.Model): title models.CharField(max_length200) content models.TextField() pub_date models.DateTimeField(auto_now_addTrue) def __str__(self): return self.title这个模型定义了三个字段title是标题最大长度200个字符content是正文内容用TextFifield表示不限长度pub_date是发布时间auto_now_addTrue表示创建时自动填入当前时间不需要手动赋值。定义好模型之后你需要做两件事。第一件事是生成迁移文件python manage.py makemigrations blog这个命令会检查models.py相比上一次有什么变化然后把变化记录到一个文件里。你可以在blog/migrations/目录下看到一个以数字开头的py文件。第二件事是执行迁移python manage.py migrate这个命令会把迁移文件中的变化真正应用到数据库也就是执行建表操作。为什么非要分两步而不能一步到位因为makemigrations相当于“写计划书”migrate相当于“执行计划”。计划书可以反复修改确认无误后再执行这样更安全。在实际项目中你经常会改模型定义makemigrations会生成新的迁移文件migrate则在新文件上执行数据库的版本演进过程被完整记录。4.4 Django Admin零代码的后台管理系统Django的自带Admin后台是最打动新人的功能。你只需要在blog/admin.py里注册模型from django.contrib import admin from .models import Article admin.site.register(Article)然后访问http://127.0.0.1:8000/admin/输入管理员账号密码就能看到一个可以增删改查Article数据的管理界面。管理员账号需要用命令创建python manage.py createsuperuser按提示输入用户名、邮箱可空、密码就行。用Admin后台管理数据对于开发阶段快速录入测试数据非常方便。而且Admin的界面是可以定制的比如设置列表显示的字段、添加搜索框、过滤器等。这些功能都通过继承admin.ModelAdmin类实现不用写一行HTML代码from django.contrib import admin from .models import Article admin.register(Article) class ArticleAdmin(admin.ModelAdmin): list_display (title, pub_date) search_fields (title,)这样后台的文章列表就会显示标题和发布时间两列并且支持按标题搜索。麻雀虽小五脏俱全真实的商业项目里Admin后台经常被当作内部运营管理系统来用非技术人员通过这个界面更新网站内容研发人员省去了写重复后台的功夫。5. 模板与静态文件让页面好看一点5.1 模板语法数据怎么渲染到HTML里光返回“你好Django”是没法看的你需要真正的HTML页面。Django的模板系统允许你在HTML文件里嵌入模板语法让页面内容动态生成。在blog目录下创建templates/blog/index.html文件内容如下!DOCTYPE html html head meta charsetutf-8 title我的博客/title /head body h1欢迎来到我的博客/h1 ul {% for article in articles %} li{{ article.title }} - {{ article.pub_date }}/li {% endfor %} /ul /body /html然后修改views.py里的index函数from django.shortcuts import render from .models import Article def index(request): articles Article.objects.all().order_by(-pub_date) return render(request, blog/index.html, {articles: articles})这里面的变化有三个Article.objects.all()查询出所有文章order_by(-pub_date)按发布日期倒序排列前面的负号表示倒序。render函数接收请求、模板路径、上下文数据三个参数把数据渲染到模板里再返回给浏览器。模板里{% for %}是循环标签{{ article.title }}是变量输出。这套语法和Python本身很接近学起来没有难度。但有几个细节要注意模板中如果变量不存在Django默认渲染为空字符串而不报错这在调试时容易掩盖问题。如果你希望更严格地暴露问题可以在settings.py里把TEMPLATES配置中的OPTIONS增加一项string_if_invalid设置为一个明显有提示的值。5.2 模板继承告别重复的HTML如果每个页面都写一套完整的HTML你的工程量会翻好几倍。Django模板系统支持继承做法是定义一个基础模板base.html子模板继承基础模板并覆盖其中部分模块。base.html长这样!DOCTYPE html html head meta charsetutf-8 title{% block title %}我的网站{% endblock %}/title /head body header nav导航栏/nav /header main {% block content %}{% endblock %} /main footer底部信息/footer /body /html子模板index.html只需要写{% extends base.html %} {% block title %}博客首页{% endblock %} {% block content %} {% for article in articles %} h2{{ article.title }}/h2 p{{ article.content }}/p {% endfor %} {% endblock %}这个机制和Python面向对象里的继承几乎一个道理。基础模板定义好布局和公共部分子模板只管需要变化的内容。项目的页面越多模板继承的收益越明显。5.3 静态文件的正确姿势CSS、JavaScript、图片这些统称静态文件。Django对静态文件的处理分“开发”和“生产”两种模式。开发模式最简单在应用目录下创建static文件夹里面放你的CSS和JS文件。然后模板里用{% load static %}加载静态文件支持再用{% static 路径 %}引用文件资源。比如在blog应用下创建static/blog/style.css然后在模板顶部加上{% load static %} link relstylesheet href{% static blog/style.css %}这样浏览器就能正确加载样式文件了。但这里有个新手必踩的坑修改了CSS文件后页面没变化。这通常不是你的代码问题而是浏览器缓存了旧文件。解决办法是在引用路径上加版本号{% static blog/style.css %}?v20240101每次修改都更新这个版本号浏览器就会重新加载。更专业的做法是配一个自动给静态文件加哈希值的工具但新手阶段用version参数就够了。生产模式下的静态文件处理我会在部署部分详细说明。这里只需要记住Django生产环境默认不提供静态文件服务需要专门处理这一步。6. 搭建一个完整的博客系统6.1 从零开始的项目需求梳理理论知识讲了不少现在做一个完整的实战项目来串联所有知识。我们的目标是搭建一个简易博客系统功能包括首页展示全部文章列表按发布时间倒序排列点击文章标题进入详情页展示文章全文后台通过Admin管理文章、分类和标签支持通过URL访问不同分类下的文章这个项目麻雀虽小但涵盖了Web开发中最高频的“增删改查”路径做完它你对Django的理解会非常扎实。6.2 模型设计博客的核心三要素对于博客系统至少需要三个模型文章、分类、标签。它们的关系是一篇文章属于一个分类但可以打多个标签。这在数据库设计上称为多对多关系。在blog/models.py里定义from django.db import models class Category(models.Model): name models.CharField(max_length100) def __str__(self): return self.name class Tag(models.Model): name models.CharField(max_length100) def __str__(self): return self.name class Article(models.Model): title models.CharField(max_length200) content models.TextField() category models.ForeignKey(Category, on_deletemodels.CASCADE) tags models.ManyToManyField(Tag, blankTrue) pub_date models.DateTimeField(auto_now_addTrue) def __str__(self): return self.title这里面有个重要参数on_deletemodels.CASCADE它表示当一个分类被删除时属于这个分类的所有文章也会被自动删除。另外还有models.SET_NULL、models.PROTECT等选项选择哪种取决于业务需求。CASCADE最省心但如果你希望保存文章而在分类被删时报错就要用PROTECT。多对多关系ManyToManyField会自动生成一张中间表来存储文章和标签的关联关系你不需要手动创建这张表Django会帮你管理。6.3 视图与URL配置页面级联的完整链路博客需要的视图函数有首页列表、文章详情、分类列表。在views.py里实现from django.shortcuts import render, get_object_or_404 from .models import Article, Category def index(request): articles Article.objects.all().order_by(-pub_date) return render(request, blog/index.html, {articles: articles}) def article_detail(request, article_id): article get_object_or_404(Article, pkarticle_id) return render(request, blog/article_detail.html, {article: article}) def category_list(request, category_id): category get_object_or_404(Category, pkcategory_id) articles category.article_set.all().order_by(-pub_date) return render(request, blog/category_list.html, {category: category, articles: articles})这里有几个细节值得展开。get_object_or_404是Django的一个便捷方法它在查询不到对象时返回404错误页面而不是抛出异常。这比你手动写try-except然后返回HttpResponseNotFound要简洁很多。category.article_set.all()是Django ORM中反向查询的语法。因为Article通过ForeignKey关联到Category那么从Category这一端查询它关联的所有文章就是用article_set这个默认名字。这个命名规律可以记一下模型名小写加下划线加set。然后配置URL。应用中的URL一般放在应用自己的urls.py里再通过项目根urls.py统一include# blog/urls.py from django.urls import path from . import views urlpatterns [ path(, views.index, nameindex), path(article/int:article_id/, views.article_detail, namearticle_detail), path(category/int:category_id/, views.category_list, namecategory_list), ]# myproject/urls.py from django.contrib import admin from django.urls import path, include urlpatterns [ path(admin/, admin.site.urls), path(, include(blog.urls)), ]这里int:article_id是URL参数捕获的语法尖括号里的int表示这个参数必须是整数article_id是传递给视图函数的关键字参数名。使用这个语法访问/article/1/时article_id就是1。给URL命名是个好习惯。通过nameindex模板中可以用{% url index %}动态生成URL好处是当路由路径改变时模板中的链接不需要依次手动修改。6.4 模板层完整示例从列表到详情列表页模板blog/index.html{% extends base.html %} {% block content %} h1最新文章/h1 ul {% for article in articles %} li a href{% url article_detail article.id %}{{ article.title }}/a span{{ article.category.name }}/span span{{ article.pub_date }}/span /li {% empty %} li暂无文章/li {% endfor %} /ul {% endblock %}详情页模板blog/article_detail.html{% extends base.html %} {% block content %} h1{{ article.title }}/h1 p分类{{ article.category.name }} | 发布日期{{ article.pub_date }}/p div {{ article.content|linebreaks }} /div p标签 {% for tag in article.tags.all %} span{{ tag.name }}/span {% endfor %} /p {% endblock %}模板中的{% empty %}是for循环为空时显示的占位内容数据列表为空时比写if判断更简洁。{{ article.content|linebreaks }}中的竖线是Django模板过滤器linebreaks过滤器会把纯文本中的换行符转成HTML的p标签数据库里存的换行到页面上才能正确显示成段落。6.5 数据填充与页面验证在写代码时你需要一些数据来验证效果。数据通常有两个来源一是Django Admin后台手动录入二是用Python脚本批量生成。Admin后台录入适合少量数据但如果你要测试分页和性能最好用脚本生成成批的数据。在项目目录下用python manage.py shell进入Django的交互式Shell环境执行from blog.models import Category, Article, Tag c Category.objects.create(namePython) t Tag.objects.create(nameDjango) for i in range(20): a Article.objects.create(titlef第{i}篇文章, content内容 * 100, categoryc) a.tags.add(t)这段代码会创建1个分类、1个标签和20篇文章。注意create方法返回的对象就是新创建的记录用变量接收后可以继续操作比如a.tags.add(t)建立了文章和标签的关联关系。数据有了之后访问首页应该能看到20篇文章的标题列表点击标题能进入详情页点分类能筛选出对应文章。这个博客系统虽然简单但“增删改查”的链路已经完整了。7. 数据可视化Django与图表的不解之缘7.1 数据可视化在Django项目里的典型用法很多人在“Django”和“数据可视化”之间划不上等号实际上这两个词经常一起出现。尤其是做后台管理系统或数据分析平台时把数据库里的统计结果变成图表展示出来是一个高频需求。Django本身不提供图表能力但它非常适合作为数据可视化的后端支撑。典型的做法是Django从数据库取出数据通过JSON接口传递给前端前端用ECharts或Chart.js渲染图表。数据计算和清洗放在Django里用ORM聚合函数甚至Pandas处理都行前端只负责把数据画出来。7.2 后端提供JSON数据接口先安装Django REST Framework这是Django生态下最流行的API开发框架pip install djangorestframework在settings.py的INSTALLED_APPS中加入rest_framework然后在blog应用里创建一个api.py文件写一个返回JSON数据的视图from django.http import JsonResponse from django.db.models import Count from .models import Article, Category def article_stats(request): # 统计每个分类下的文章数量 stats Category.objects.annotate(countCount(article)) data [{name: c.name, value: c.count} for c in stats] return JsonResponse(data, safeFalse)annotate是Django ORM中的聚合查询方法Count(article)表示统计每个分类关联的文章数量。返回的JSON数据格式为[{name: Python, value: 20}, {name: Django, value: 10}]这种格式正是ECharts饼图直接需要的。在URL里加上这个接口path(api/article-stats/, views.article_stats)7.3 前端用ECharts渲染图表在模板中引入ECharts的CDN然后写一个简单的饼图!DOCTYPE html html head meta charsetutf-8 title文章统计/title script srchttps://cdn.jsdelivr.net/npm/echarts5/dist/echarts.min.js/script /head body div idchart stylewidth: 600px; height: 400px;/div script fetch(/api/article-stats/) .then(response response.json()) .then(data { var chart echarts.init(document.getElementById(chart)); chart.setOption({ title: { text: 各分类文章数量 }, series: [{ type: pie, data: data }] }); }); /script /body /html这段代码用了浏览器的原生fetch方法向Django后台请求JSON数据然后交给ECharts渲染。ECharts的使用思路是这样的init指定挂载的DOM元素setOption定义图表的配置项和数据。配置项中type: pie就是饼图改成line就是折线图改成bar就是柱状图配置灵活度很高。数据可视化完整链路跑通后你会发现Django其实是个很称职的“数据中台”——它不仅负责网页渲染还能给任何前端提供结构化的数据接口。8. 常见问题与性能优化方向8.1 开发期高频报错速查表我整理了Django开发中最高频的几个报错以及对应的解决思路写成表格方便排查报错信息原因解决方法ModuleNotFoundError: No module named django未安装Django或未激活虚拟环境检查虚拟环境状态执行pip install djangoDisallowedHostALLOWED_HOSTS未配置或配置错误开发环境改成ALLOWED_HOSTS [*]ImproperlyConfigured: mysqlclient...使用MySQL数据库但缺驱动安装mysqlclient或pymysql并配置TemplateDoesNotExist模板路径配置错误或文件位置不对检查templates目录和文件名确认INSTALLED_APPS已包含应用OperationalError: no such table未执行迁移执行python manage.py migrateField id expected a number but got...URL传参类型不匹配检查URL路由的int转换器和视图函数参数静态文件404静态文件路径或配置问题开发时使用django.contrib.staticfiles确认static目录位置8.2 查询优化N1问题新手写Django ORM时最容易忽略的问题是N1查询。什么意思看这段代码articles Article.objects.all() for article in articles: print(article.category.name)第一行查询出所有文章这本身是一次数据库查询。但是在循环体里访问article.category时每篇文章都会再发动一次查询去取分类信息。如果文章有100篇总查询次数会达到1100101次这就是N1问题。解决办法很简单用select_related预取关联对象articles Article.objects.select_related(category).all()这样Django会用一条带JOIN的SQL把文章和分类的数据一次性查出来后续访问article.category不会产生额外查询。select_related适用于ForeignKey和OneToOneField这类“单值关联”查询。多对多关系要用prefetch_relatedarticles Article.objects.prefetch_related(tags).all()这个会把关联的tags数据一次性查出来缓存到内存中。养成在列表页查询时顺手加上select_related和prefetch_related的习惯性能差距在数据量大的时候是数量级的差别。8.3 安全配置必须知道的几件事Django在安全性上做了很多内置防护但你需要在settings.py里正确启用它们。有几个关键配置DEBUG模式。生产环境必须将DEBUG设为False。DEBUGTrue时一旦程序出错页面上会显示完整的报错信息、服务器路径、甚至环境变量这些信息对攻击者来说非常有价值。SECRET_KEY。部署生产环境时SECRET_KEY要换成随机字符串可以用python -c from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())生成。不要硬编码在代码里最好存放在环境变量中。CSRF防护。Django默认开启了CSRF中间件POST表单会自动校验CSRF Token你在模板的form里加{% csrf_token %}标签就行。不要因为嫌麻烦关掉它。8.4 后续学习路线建议如果你完整走完这个实战项目已经算是入门了。接下来的学习路线可以按顺序往下走学习基于类的视图Class-Based Views提高代码复用率学习Django REST Framework构建API现在前后端分离是主流学习数据库迁移的进阶用法和复杂查询学习Celery处理异步任务再用Nginx和uWSGI/Gunicorn部署上线。我自己带过的学生有一个共同特征一开始觉得Django很神秘跑通第一个项目之后会兴奋一阵子然后再遇到各种问题时会怀疑自己熬过这个阶段之后Django大部分套路都是按部就班。Web开发的门槛真的不高Django又帮你把门槛压到了很低的位置。把这篇教程里的代码亲手敲一遍比看十篇教程都管用。动手吧。
返回列表