My takeaways from DjangoCon EU 2025
作者在 DjangoCon EU 2025 上分享了他的收获。文章重点介绍了数据库优化技巧,如使用 `select_for_update` 锁定行、BigInt 主键、数据库分区和索引优化。还提到了各种工具和库,例如 `strace`、`django-auto-prefetch` 和 `django-csp`。此外,文章还总结了最佳实践,如在 PR 中导出 `sqlmigrate` 和在测试中计算数据库查询。最后,作者分享了对 Django 社区的观察,以及对欧洲生活和会议氛围的感受,并推荐了一些优秀的演讲。
我从 DjangoCon EU 2025 上的收获
tl;dr: 都柏林和 Django 社区都很棒。
Zach Bellay 发表于 2025 年 4 月 26 日
12 分钟,2212 字
以下是我在爱尔兰都柏林举行的 DjangoCon EU 2025 上学到的一些最有趣的东西,部分由 AI 辅助编写:演讲链接
我整理的最佳演讲列表在文章底部。
我在 DjangoCon EU 2025!
数据库
- 如何从 Django 锁定数据库行:
select_for_update
在进行更改之前锁定一行,确保并发环境中的数据一致性。 - 尽快迁移到 BigInt 主键:始终使用 BigInt (64 位) 或 UUID 作为主键。如果您的表接近 21 亿条记录(32 位整数的限制),您可以使用负值来增加范围,但有一些注意事项。演讲
- 按租户分区数据库表:
PostgresPartitionedModel
mixin 帮助根据值将数据分区到单独的 PostgreSQL 分区中,从而提高大型表的性能。- 有关详细信息,请参阅
django-postgres-extra
包 GitHub
- 有关详细信息,请参阅
- 在 Postgres 索引中节省 99.8% 的空间:始终显式设置外键的
db_index
。 默认情况下,外键会被索引,但您可以进一步优化:- PostgreSQL 为空值构建索引,但您可以向
Index
添加条件以显着减小索引大小(最多缩小约 99%)。
- PostgreSQL 为空值构建索引,但您可以向
# 部分索引示例
class Restaurant(models.Model):
restaurant_chain = models.ForeignKey(..., db_index=False)
class Meta:
indexes = [
models.Index(
fields=["restaurant_chain"],
condition=~models.Q(restaurant_chain=None),
),
]
- 在 Pytest 中编写性能测试:编写将数据加载到数据库并记录视图花费时间的测试,以确保良好的性能(或查看回归)。
- 检查笔记本电脑与云服务器的 IO 速度:如果您的数据库/应用程序在云端速度较慢,请将云磁盘速度与笔记本电脑的磁盘速度进行比较,以查看瓶颈是硬件还是 I/O。
- TODO:插入可以执行此操作的命令(需要找到在 YouTube 上发布的演讲)
- TCP_NODELAY 和 Nagle 算法:如果您遇到每秒约 25 个请求或每次调用 40 毫秒左右的瓶颈,则可能是由于 TCP_NODELAY 或 Nagle 算法造成的。 可以使用环境变量禁用它们以提高性能。
工具 & 库
strace
:一个 Linux 实用程序,用于检查进程发出的系统调用(不需要 root)。django-neopolitan
:使用CRUDView
轻松创建 CRUD 视图(来自第一次 htmx 演讲)。django-auto-prefetch
:自动预取相关对象以减少数据库查询。GitHubdjango-csp
:用于 Django 的内容安全策略——将合并到 Django 核心中。django-otp-webauthn
:启用 Face ID 或指纹登录(密码密钥支持)。演讲仓库django-two-factor-auth
:用于 Django 中的 2FA/MFA。silence-lint-error
:添加内联 linter 静默,以逐步引入 linting 规则。PyPI- 使用内联 linter 静默来逐步实施 linting 规则(“堵住漏洞,然后把船上的水舀出去”)。
MaxMind
:推荐使用他们的数据库来阻止“坏人”(不仅仅是机器人)。- 一个糟糕的机器人是一些点击
/xmlrpc.php
的脚本,而一个坏人是恶意解决验证码,使用合法的电子邮件/电话号码,并对您的网站做坏事(例如试图托管加密货币矿工等)的人。
- 一个糟糕的机器人是一些点击
dj-angles
:在 Django 模板中使用类似 HTML 的元素,例如代替 {% include 'partial.html' %} 文档
最佳实践
- 在 PR 中导出 sqlmigrate:设置一个 GitHub Action,以便任何带有迁移的 PR 输出
sqlmigrate
的内容,强制开发人员审查生成的 SQL。- 声明的例子是为了
- 在测试中计算数据库查询:在 pytest 中,计算每个测试的查询数量,如果超过阈值则失败。 添加一个装饰器来绕过 WIP 或异常。 目的是找到产生过多您不期望的数据库查询的代码。
- 在演讲中,演讲者展示了一些无辜的代码,例如
create_customer_profile()
,它有 36K 个数据库查询
- 在演讲中,演讲者展示了一些无辜的代码,例如
- 清理旧标志:避免重复使用旧的 feature flag——请参阅 Knightmare(4.6 亿美元的错误)了解原因。阅读更多
Django & 社区
- Django Admin 定制:Canonical 工程负责人链接了一个类似 Django 电子表格的应用程序,用于管理 Canonical 软件质量 Django 仪表板 Github
- 我认为这很酷有两个原因
- 1:信息布局非常密集,带有表格
- 2:高度定制的 django admin,虽然与作者交谈过,但他表示他认为这非常 hacky 且不可维护,并且他希望将其移出 django admin 并使用 htmx
- 1:信息布局非常密集,带有表格
- 我认为这很酷有两个原因
- Django 功能提案:现在在 GitHub issues 上讨论!请看这里——这很棒,因为 Github 是开发者们经常出没的地方。
- 用 Rust 编写的 Django 模板后端:一个用 Rust 编写的 Django 模板渲染后端正在开发中。GitHub
- Roasting App:用 htmx 制作的 Roasting app,使用了 hyperscript,至少是一个有趣的案例研究。GitHub
建模 & 架构
- Schema-aware EAV 建模:对于用户定义自己的模型/表单的应用程序,通用的 EAV (Entity-Attribute-Value) 系统可以提供帮助。 例子:
boat = Entity.objects.with_attributes(object="MaritimeBoat").first()
print(boat.size) # 32 meters
模板 & 杂项
{% spaceless %}
:用于删除 Django 模板中空格的模板标签。- B+ 树:B+ 树数据结构的高级概述。
一些使用 Django 的公司
- Octopus Energy:英国/澳大利亚能源公司
- Divio:为代理商提供的 django 托管
- codered.cloud:简易的 django 托管
- Monit:停车管理系统
- Gem Logic:珠宝 ERP
- Zelthy:印度的定制医疗保健应用开发平台
平台 & 值得关注的事物
- Divio:供代理商轻松托管多个 Django 项目的平台。
- Django 静态站点生成器:
- 100 Words/Day Blog:softwarecrafts.uk/100-words
氛围
- 似乎人们更喜欢
django-cotton
而不是django-components
,因为它的 HTML 类似语法 - 有很多关于 django 作为项目的治理的讨论,基本上只有极少数人参与或贡献(超级巨星)
(作为一名美国人在欧洲的见闻)
- 每个人都很友善,欧洲的生活必需品似乎比美国好得多——德国人不用支付大学学费,有国家资助的医疗保健,没有“随意”就业,公共交通发达,与美国相比,育儿费用便宜得多等等
- 许多会议参与者为政府工作
- 都柏林也面临着生活成本危机,面临着不愿分区管制 (NIMBYism) 的阻力。
- 都柏林所有的 Uber 实际上都是获得许可的出租车司机,他们通过应用程序叫车。 这似乎比典型的零工型 Uber 司机对司机的剥削要少得多。
- 将旧金山与都柏林相比,街上几乎没有无家可归者或疯子,也没有粪便(我不喜欢落入刻板印象,但这是真的,尽管我也去了旅游区)
最佳演讲
我带着较低的期望去的,因为演讲题目看起来不太好,但许多演讲的质量让我感到震惊。 一些最好的演讲(一旦它们在 YouTube 上发布,我将重新观看):
- Turn back time: Converting integer fields to bigint using Django migrations at scale
- Data-Oriented Design
- 由 Adam Johnson (adamchainz) 主讲,他维护着许多流行的 django 包
- Django + HTMX: Patterns to Success
- How to get Foreign Keys horribly wrong in Django
- 100 Million Parking Transactions Per Year with Django
- Dynamic models without dynamic models
- Just-in-Time Development with Django and HTMX: Faster, Leaner, and Smarter
- 我之后和这位演讲者交谈,问他他们是如何在嵌套模态窗口中更新 widget,以及在嵌套模态窗口中创建一个新对象之后更新表单的。 他向我展示了他是怎么做的,我已经尝试了 8 个月了!
- Anatomy of a Database Operation
- Django Admin at Scale: From Milliseconds to Microseconds
- 许多闪电演讲都很棒,因为演讲者必须直奔主题
源材料: 我学到的东西:
select_for_update
—— 在更改之前锁定一行- 使用
strace
Linux 实用程序来查看 Linux 进程正在调用哪些系统调用(不需要 root) PostgresPartitionedModel
- mixin,用于根据某个值将数据分区到单独的 pg 分区中- 确保您的主键是 BigInt! (64 位,而不是 32 位)或 UUID
- 如果您的表接近 21 亿条记录,您可以使用负值来使表中的条目数量翻倍(42 亿),但有一些注意事项
- 如果您遇到每秒 25 个请求或每次调用 40 毫秒的瓶颈,则可能是 TCP_NODELAY 或 nagle 算法,可以通过一些环境变量禁用
- 始终显式设置外键的 db_index
- 默认情况下,外键具有与之关联的索引
- Postgres 仍然为空值构建索引,因此通过向
Index
添加条件,您可以显着减小索引大小约 99%
# source https://ckrybus.com/snippets/django-foreign-key-partial-index/
class RestaurantChain(models.Model):
name = models.CharField(max_length=512)
class Restaurant(models.Model):
name = models.CharField(max_length=512)
restaurant_chain = models.ForeignKey(
RestaurantChain, on_delete=models.CASCADE, null=True, blank=True, db_index=False
)
class Meta:
indexes = [
models.Index(
fields=["restaurant_chain"],
condition=~models.Q(restaurant_chain=None),
),
]
- 使用
django-neopolitan
CRUDView
用于 CRUD 视图 -- 来自第一次 htmx 演讲 - 如果您发现您的数据库/应用程序在云端速度慢得多,请将云磁盘速度与笔记本电脑磁盘速度进行比较,以查看瓶颈实际上是数据库中的硬件还是其他 IO
- TODO:插入可以执行此操作的命令(需要找到在 YouTube 上发布的演讲)
- 用于管理 Canonical 软件质量的电子表格 Django 仪表板
- https://github.com/canonical/dashboard
- 我认为这很酷有两个原因
- 1:信息布局非常密集,带有表格
- 2:高度定制的 django admin,虽然与作者交谈过,但他表示他认为这非常 hacky 且不可维护,并且他希望将其移出 django admin 并使用 htmx
- 1:信息布局非常密集,带有表格
- 创建一个 github action,以便任何带有迁移的 PR 输出 sqlmigrate 的内容,以便开发人员必须查看 SQL
- 这样开发人员必须查看生成的 SQL
django-csp
将进入 django 核心- 使用 Face ID 或指纹通过 django (passkey) 登录的能力:
django-otp-webauthn
- 演讲 GitHub 仓库: https://github.com/knyghty/talk-passkeys/tree/main
- django-auto-prefetch
- https://github.com/tolomea/django-auto-prefetch
- 关于模式感知通用 EAV 建模的精彩演讲
- 演讲者有一个产品,允许用户任意定义模型 + 表单,因此他必须构建一个通用的基于 EAV 的建模系统来处理该任意数据
- 基本上,用户会定义一个模式,然后他构建了一种获取这些对象的通用方法,类似于
boat = Entity.objects.with_attributes(object="MaritimeBoat").first()
print(boat.size) # 32 meters
* https://pretalx.evolutio.pt/djangocon-europe-2025/talk/DGQ9JD/
- 清理旧标志:Knightmare(4.6 亿美元的错误)
- 高频交易公司重复使用旧标志,导致出现意外行为
- https://dougseven.com/2014/04/17/knightmare-a-devops-cautionary-tale/
{% spaceless %}
模板标签删除模板中的空格- 2FA/MFA :
django-two-factor-auth
- 编写性能测试!
- 编写一个将大量数据加载到数据库并记录视图花费时间的测试
- 添加内联 linter 静默,以便您可以逐步在现有代码库中添加 linting 规则
- “堵住漏洞,然后把船上的水舀出去”
- https://pypi.org/project/silence-lint-error/
- 在 pytest 中,计算每个测试的查询数量,如果高于阈值,则使测试失败。
- 在测试中添加一个装饰器,以便能够在可以或正在进行时绕过/忽略
- 建议使用 MaxMind 阻止“坏人”(不同于坏机器人,因为通常可以用 reCaptcha 缓解机器人,但人类不是,因此 MaxMind 会保留这些东西的数据库,您可以根据该数据库进行阻止)
- B+ 树的高级概述
- 用 htmx 制作的 Roasting app,使用了 hyperscript,至少是一个有趣的案例研究
- https://github.com/scriptogre/roast-roulette
- 一个新的 django 模板渲染后端正在用 rust 编写:
- https://github.com/LilyFoote/django-rusty-templates
- django 功能提案现在可以在 github issues 上讨论!
- https://github.com/django/new-features/issues/
库: 平台:
- Divio,供代理商轻松托管多个 django 项目
值得关注的事物:
- Django 静态站点生成器
- https://django-distill.com/
- calico-ssg 基于 Django 的静态站点生成器
- https://calico-ssg.com/techstack.html
- 有一些有趣的依赖项
- 100 words/day 博客文章
- https://softwarecrafts.uk/100-words