Django中我一直在享受的更多特性

Lobsters Hottest 新闻

摘要

Julia Evans分享了她在构建后端网站时对Django查询构建器和模板过滤器的正面体验,称赞了它们的可读性和便利性。

<p><a href="https://lobste.rs/s/x5ewgv/some_more_things_about_django_i_ve_been">评论</a></p>
查看原文
查看缓存全文

缓存时间: 2026/07/22 04:17

# 最近在 Django 中让我感到愉快的几个方面 来源:https://jvns.ca/blog/2026/07/21/more-nice-django-things/ 大家好!我目前正在经历一段有趣的探索:尝试用类似 2010 年的方式来制作网站——使用 SQL 数据库,并在后端渲染 HTML。这段旅程很有意思,因为用这种方式建站对我来说并不觉得“容易”:我从没在 2000 年代或 2010 年代学会怎么做,所以有很多东西需要学习。接下来聊聊 Django 的一些功能,它们让我觉得构建这类网站比以前尝试 Go 标准库或 Flask(并且失败了)时更有把握。我也会提一下遇到的一些问题。 ### 为什么学习像 2010 年那样建站? 之前我熟练使用的建站工具包括: - 静态站点生成器(比如这个博客) - 做一些有趣 JavaScript 效果的静态站点(比如这个 SQL 在线练习台) - 简单的 Vue.js 单页应用,后端用 Lambda 或 Go(比如 mess with dns) 我非常喜欢这种前端为主的思路做极简单的应用。但当我想做一个包含多页(而不是仅仅一页)的东西时,我对那些需要大量前端代码的方案并不太兴奋。所以我想试试后端。 写一个以后端为主、尽可能少用 JS 的网站,对我来说感觉和写一个以 JS 单页为主、后端尽可能简单的网站其实很像——虽然它们看起来是相反的。两种情况下,我只是想把尽可能多的逻辑放在一个地方。 现在说说我对 Django 的一些想法吧! ### 我很喜欢查询构建器 我学会了在 Django 中定义一个“查询集”类,里面包含一堆方法,每个方法对应不同的 `WHERE` 语句,方便在构建查询时使用。下面是我在视图代码中的用法(定义好所有方法含义之后): `Events.objects.approved().for_tab(tab).with_festivals(tab_params.festival_slugs).is_free(tab_params.free).is_outdoors(tab_params.outdoors)` 这是定义这些方法的方式: ```python class EventQuerySet(SearchableQuerySetMixin, models.QuerySet): def approved(self): return self.filter(approved_at__isnull=False) def future(self): today = timezone.localdate() return self.filter(end__gt=self._midnight(today)) def with_tags(self, tags): if tags: return self.filter(tags__name__in=tags).distinct() return self ``` 定义过滤器的语法不是我最喜欢的,但我大部分时间只是调用这些方法,感觉非常可读且好用,也让我以后想去探索其他查询构建器库。以前我觉得“我会写 SQL,谁需要查询构建器?”,但这种结构确实让代码读起来很舒服。 我找到了一个例子,有人用 Python 写了一个自己的小型查询构建器,打算以后阅读一下,思考自己是否喜欢更精简的版本。 ### 模板过滤器很棒 Django 模板中有很多非常实用的过滤器,对生成 HTML 超级有用。我目前用过的有: - 将纯文本 URL 转为链接,或将换行转为 `<br>`:`{{ event.description|urlize|linebreaksbr }}` - 格式化日期:`{{ row.date|date:"M j" }}` - `json_script`:将 Python 字典自动转为 JSON 并安全地插入 HTML 的 `<script>` 标签中 这些虽然都是小功能,但感觉有了它们之后,写起来方便多了。 ### `querystring` 很酷 我想我最喜欢的模板过滤器是 `querystring`。在这个网站上,我们有时用类似 `?date=2026-06-01` 的筛选参数来决定显示内容。`querystring` 可以生成一个只改动一个参数的链接,比如链接到前一个日期: `<a href="?querystring ...>...</a>` 或者去掉 `outdoors` 参数: `<a href="?querystring ...>...</a>` ### 自动数据库迁移依然很棒 我仍然非常喜欢 Django 的自动数据库迁移系统。只需编辑模型添加新字段之类,然后 Django 自动生成迁移文件,这太棒了。到目前为止我们做了 19 次数据库迁移,可能还会有更多!能随着对问题的理解变化轻松修改数据库,这对我来说意义重大。 ### 我不想用继承来组织代码 Django 的文档有时提供使用基于类的视图和继承来组织视图代码的选项。例如,我有四个共享很多代码的视图,我可以用继承来管理它们:定义一个父类,然后让其他视图继承它。我试过,但很不喜欢用继承来在视图间共享代码。我转而使用函数,就像这篇文章倡导的那样,这样直接多了。我在 Python 中使用继承的经历从来没有好过,以后也不想再试了。但我不介意用继承来实现 Django 本身提供的接口:比如定义查询集时,需要写 `class EventQuerySet(SearchableQuerySetMixin, models.QuerySet)`。我不去多想,似乎也能工作。 (作为补充:我一直在练习用“对我来说,某事感觉不好,我更喜欢另一件事”的方式表达我的编程观点。我链接的那篇文章说基于函数的视图是“正确的方式”。我并不是很在意它是否“正确”,但知道其他人和我对继承有类似的感觉,让我感觉得到印证。) ### 我不知道该如何考虑 Django 的性能 后来 LLM 爬虫发现了我们的网站,开始每秒发送大概 10 个请求。我屏蔽了它们,目前有效,但让我思考网站的性能容量。我习惯写 Go 后端,性能情况一般很直接(通常就是足够快),而 Django 网站完全不同。 简单的负载测试(用 `ab -n 1000 -c 1`)显示,目前我们每秒钟大约能处理 2-3 个请求(在每月约 10 美元的虚拟机上)。我很想钻牛角尖,做一堆性能分析来找出慢在哪里并优化(有 py-spy 这样的工具,非常好用,而且性能分析很有趣!)。但我真的不知道 Django 网站的性能应该期望多少,以及应该从更高层面怎么思考。 我还没有搞清楚的事情: - 如果一个网站会偶尔出现流量突发,我是否需要考虑扩展能力? - 是否需要设计网站让更多东西可以被缓存?(而且必须要做吗?缓存太难搞对了!) - Django 性能文档说 Jinja 模板更快,我是否需要考虑切换模板引擎? - 文档还说“`{% block %}` 比 `{% include %}` 更快”,不知道差异大不大,如果大,是为什么。 ### 模板缓存可能很重要 我觉得关于 Django 我学到的一件事是,因为它是一个“框架”,很容易不小心配置错误。比如,刚才我思考网站为什么慢时,读了 Django 性能文档,注意到一句话: > 启用缓存的模板加载器通常能大幅提升性能,因为它避免每次渲染时都编译模板。 顺着链接点进去,我发现缓存的模板加载器默认应该是开启的,但我之前因为做别的事不小心把它关掉了。我觉得“我意外关掉了默认开启的模板缓存加载器”这件事就是例子,说明我仍然觉得 Django 的设置文件令人困惑和困难。我想我以后进去修改时需要小心。 总之我不想过多深入网站性能优化。就像我说过的,我很容易对性能分析产生兴趣,但实际上我对性能分析已经了解很多,这并不是目前最重要的学习内容。 ### 今天就先聊到这儿了! 以后我可能还会继续说说 Django 中让我喜欢(或觉得困难!)的地方。最近试着写一些短一点的博客文章。

相似文章

我喜爱 Django 之处

Hacker News Top

一篇颂扬 Django 中间件与模型抽象的文章,阐述它们如何在 Buttondown 代码库中提供长期杠杆效应。

两种SQL查询构建器

Lobsters Hottest

本文探讨了FunSQL.jl,一个用于SQL查询构建的Julia库,并将其数据导向接口与其他查询构建器进行了比较,突出了其组合特性与完整SQL支持的独特结合。

插件案例研究:Pluggy

Eli Bendersky

一篇博客文章,探讨了Pluggy——这是一个最初源自pytest的Python库,用于构建插件系统。内容包括其工作原理以及如何将其与一个玩具级HTML转换工具配合使用。