你好!我最喜欢的事情之一就是学习一些我从未尝试过但已经存在了20多年的老旧技术。当我遇到的所有问题都已经被解决过上千次,我可以轻松搞定一切的时候,感觉真的太棒了。
我一直很想学习像 Rails、Django 或 Laravel 这样流行的 Web 框架,但一直没能真正付诸行动。几个月前,我开始学习 Django 来做一个网站,目前为止感觉还不错,以下是一些简单的笔记!
比 Rails 少些魔法
2020 年我花了一些时间学习 Rails ,虽然它很酷,我也很想喜欢 Rails(Ruby 社区很棒!),但我发现如果我的 Rails 项目闲置几个月,当我再回来时,我很难记住如何完成任何事情,因为(例如)如果你的routes.rb中写了resources :topics ,这本身并不能告诉你topics路由在哪里配置,你需要记住或查找相关的约定。
能够放弃一个项目几个月甚至几年,然后再回来继续做下去,这对我来说非常重要(我的所有项目都是这样运作的!),而 Django 对我来说感觉更容易上手,因为它的运作方式更加明确。
在我的小型 Django 项目中,感觉只有 5 个主要文件(除了设置文件之外): urls.py 、 models.py 、 views.py 、 admin.py和tests.py ,如果我想知道其他东西(例如 HTML 模板)在哪里,通常都会从这些文件中显式引用它。
内置管理员
在这个项目中,我需要一个管理界面,用于手动编辑或查看数据库中的一些数据。Django 内置了一个非常不错的管理界面,而且我只需要编写少量代码就可以对其进行自定义。
例如,这是我的一个管理类的一部分,它设置了要在“列表”视图中显示的字段、要搜索的字段以及默认情况下如何对它们进行排序。
@admin.register(Zine) class ZineAdmin(admin.ModelAdmin): list_display = ["name", "publication_date", "free", "slug", "image_preview"] search_fields = ["name", "slug"] readonly_fields = ["image_preview"] ordering = ["-publication_date"]拥有在线关系管理(ORM)很有趣@admin.register(Zine) class ZineAdmin(admin.ModelAdmin): list_display = ["name", "publication_date", "free", "slug", "image_preview"] search_fields = ["name", "slug"] readonly_fields = ["image_preview"] ordering = ["-publication_date"]
过去我的态度是“ORM?谁需要它们?我自己写SQL查询不就行了吗!”。不过,到目前为止,我对Django的ORM还挺满意的,而且我觉得Django用__来表示JOIN方式很酷,就像这样:
Zine.objects .exclude(product__order__email_hash=email_hash)此查询涉及 5 个表:Zine.objects .exclude(product__order__email_hash=email_hash)
zines 、 zine_products 、 products 、 order_products和orders 。为了实现这一点,我只需要告诉 Django 有一个ManyToManyField关联“orders”和“products”,以及另一个ManyToManyField关联“zines”和“products”,这样它就知道如何连接zines 、 orders和products 。
我当然可以写出那个查询语句,但是写product__order__email_hash可以少打很多字,也更容易阅读,而且说实话,我觉得我需要花点时间才能弄清楚如何构建这个查询语句(除了这些连接之外,它还需要做一些其他的事情)。
我对 ORM 生成的查询的性能完全不担心,所以目前我对 ORM 非常兴奋,尽管我确信最终我会遇到一些令人沮丧的事情。
自动迁移!
ORM 的另一个优点是迁移!
如果我在models.py中添加、删除或更改字段,Django 将自动生成类似migrations/0006_delete_imageblob.py的迁移脚本。
我想如果需要的话,我可以编辑这些脚本,但到目前为止,我只是直接运行生成的脚本,没有做任何修改,效果非常好。这感觉真的太神奇了。
我意识到,现在能够轻松进行数据迁移对我来说很重要,因为我需要经常更改数据模型,才能弄清楚我想要它如何运作。
我喜欢这些文档。
我以前有个坏习惯,从来不看文档,但我现在真的很喜欢我目前为止读过的 Django 文档。这并非偶然:Jacob Kaplan-Moss 在2011 年的 PyCon 大会上做过一个关于 Django 文档文化的演讲。
例如,模型简介列出了在使用 ORM 时可能需要设置的最重要的常用字段。
使用 sqlite
在尝试使用 Postgres 时遭遇了糟糕的经历,而且完全搞不懂它在做什么之后,我决定把所有的小型网站都改用 SQLite。现在一切都好多了,而且我喜欢备份的方式,只需要执行VACUUM INTO命令,然后复制生成的单个文件就行了。
我一直在按照这些说明在生产环境中使用 SQLite 和 Django。
我认为应该没问题,因为我预计该网站每天最多只有几百次写入,远少于Mess with DNS,后者写入次数更多,而且一直运行良好(尽管写入操作分散在 3 个不同的 SQLite 数据库中)。
内置电子邮件(及更多功能)
Django 似乎非常“开箱即用”,我很喜欢这一点——如果我需要 CSRF 保护、 Content-Security-Policy ,或者想发送电子邮件,所有这些都包含在内!
例如,我希望在开发模式下将 Django 发送的电子邮件保存到文件中(这样它就不会向真人发送真实的电子邮件),这只需要进行一些配置。
我刚刚把这个settings/dev.py放进去了:
EMAIL_BACKEND = "django.core.mail.backends.filebased.EmailBackend" EMAIL_FILE_PATH = BASE_DIR / "emails"然后像这样设置生产环境的电子邮件EMAIL_BACKEND = "django.core.mail.backends.filebased.EmailBackend" EMAIL_FILE_PATH = BASE_DIR / "emails"
settings/production.py
EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend" EMAIL_HOST = "smtp.whatever.com" EMAIL_PORT = 587 EMAIL_USE_TLS = True EMAIL_HOST_USER = "xxxx" EMAIL_HOST_PASSWORD = os.getenv('EMAIL_API_KEY')这让我觉得,如果我需要其他一些基本的网站功能,Django 很可能已经内置了简单的实现方法。EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend" EMAIL_HOST = "smtp.whatever.com" EMAIL_PORT = 587 EMAIL_USE_TLS = True EMAIL_HOST_USER = "xxxx" EMAIL_HOST_PASSWORD = os.getenv('EMAIL_API_KEY')
设置文件仍然感觉很多。
我对settings.py文件仍然有点畏惧:Django 的设置系统是通过在一个文件中设置一堆全局变量来实现的,我有点担心……如果我把其中一个变量名拼错了怎么办?我怎么知道?如果我把WSGI_APPLICATION写成WSGI_APPLICATOIN = "config.wsgi.application"会怎么样?
我想我已经习惯了 Python 语言服务器在我拼写错误时告诉我,所以现在当我无法依赖语言服务器支持时,会感到有点不知所措。
今天就到这里!
我以前还没有真正成功地在项目中使用过真正的 Web 框架(目前我的网站几乎都是单个 Go 二进制文件或静态网站),所以我很想看看效果如何!
我还有很多东西要学习,我还没有真正深入了解 Django 的表单验证工具或身份验证系统。
感谢 Marco Rogers 说服我尝试一下 ORM。
(我们仍在测试 Mastodon 上的评论系统!这里是 Mastodon 上的评论!告诉我你最喜欢的 Django 功能!)
原文: https://jvns.ca/blog/2026/01/27/some-notes-on-starting-to-use-django/