5 minrss原文 ↗

Some notes on starting to use Django

Hello! One of my favourite things is starting to learn an
Old Boring Technology that I’ve never tried before but that has been around for

20+ years. It feels really good when every problem I’m ever going to have has

been solved already 1000 times and I can just get stuff done easily.

I’ve thought it would be cool to learn a popular web framework like

Rails or Django or Laravel for a long time, but I’d never really managed to

make it happen. But I started learning Django to make a website a few months

back, I’ve been liking it so far, and here are a few quick notes!

less magic than Rails

I spent some time trying to learn Rails in 2020,

and while it was cool and I really wanted to like Rails (the Ruby community is great!),

I found that if I left my Rails project alone for months, when I came

back to it it was hard for me to remember how to get anything done because

(for example) if it says resources :topics in your routes.rb, on its own

that doesn’t tell you where the topics routes are configured, you need to

remember or look up the convention.

Being able to abandon a project for months or years and then come back to it is

really important to me (that’s how all my projects work!), and Django feels easier

to me because things are more explicit.

In my small Django project it feels like I just have 5 main files (other

than the settings files): urls.py, models.py, views.py, admin.py, and

tests.py, and if I want to know where something else is (like an HTML template)

is then it’s usually explicitly referenced from one of those files.

a built-in admin

For this project I wanted to have an admin interface to manually edit or view

some of the data in the database. Django has a really nice built-in admin

interface, and I can customize it with just a little bit of code.

For example, here’s part of one of my admin classes, which sets up which fields

to display in the “list” view, which field to search on, and how to order them

by default.

@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"]

it’s fun to have an ORM
In the past my attitude has been “ORMs? Who needs them? I can just write my own SQL queries!”.

I’ve been enjoying Django’s ORM so far though, and I think it’s cool how Django

uses __ to represent a JOIN, like this:

Zine.objects

.exclude(product__order__email_hash=email_hash)

This query involves 5 tables: zines, zine_products, products, order_products, and orders.
To make this work I just had to tell Django that there’s a ManyToManyField

relating “orders” and “products”, and another ManyToManyField relating

“zines”, and “products”, so that it knows how to connect zines, orders, products.

I definitely could write that query, but writing product__order__email_hash is

a lot less typing, it feels a lot easier to read, and honestly I think it would

take me a little while to figure out how to construct the query

(which needs to do a few other things than just those joins).

I have zero concern about the performance of my ORM-generated queries so I’m

pretty excited about ORMs for now, though I’m sure I’ll find things to be

frustrated with eventually.

automatic migrations!

The other great thing about the ORM is migrations!

If I add, delete, or change a field in models.py, Django will automatically

generate a migration script like migrations/0006_delete_imageblob.py.

I assume that I could edit those scripts if I wanted, but so far I’ve just

been running the generated scripts with no change and it’s been going great. It

really feels like magic.

I’m realizing that being able to do migrations easily is important for me right

now because I’m changing my data model fairly often as I figure out how I want

it to work.

I like the docs

I had a bad habit of never reading the documentation

but I’ve been really enjoying the parts of Django’s docs that I’ve read so far.

This isn’t by accident: Jacob Kaplan-Moss has a

talk from PyCon 2011

on Django’s documentation culture.

For example the intro to models

lists the most important common fields you might want to set when using the ORM.

using sqlite

After having a bad experience trying to operate Postgres and not being able to

understand what was going on, I decided to run all of my small websites with

SQLite instead. It’s been going way better, and I love being able to backup by

just doing a VACUUM INTO and then copying the resulting single file.

I’ve been following these instructions

for using SQLite with Django in production.

I think it should be fine because I’m expecting the site to have a few hundred

writes per day at most, much less than Mess with DNS

which has a lot more of writes and has been working well (though the writes are

split across 3 different SQLite databases).

built in email (and more)

Django seems to be very “batteries-included”, which I love – if I want CSRF

protection, or a Content-Security-Policy, or I want to send email, it’s all

in there!

For example, I wanted to save the emails Django sends to a file in dev mode (so

that it didn’t send real email to real people), which was just a little bit

of configuration.

I just put this settings/dev.py:

EMAIL_BACKEND = "django.core.mail.backends.filebased.EmailBackend"

EMAIL_FILE_PATH = BASE_DIR / "emails"

and then set up the production email like this in 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')

That made me feel like if I want some other basic website feature, there’s
likely to be an easy way to do it built into Django already.

the settings file still feels like a lot

I’m still a bit intimidated by the settings.py file: Django’s settings system

works by setting a bunch of global variables in a file, and I feel a bit

stressed about… what if I make a typo in the name of one of those variables?

How will I know? What if I type WSGI_APPLICATOIN = "config.wsgi.application"

instead of WSGI_APPLICATION?

I guess I’ve gotten used to having a Python language server tell me when I’ve

made a typo and so now it feels a bit disorienting when I can’t rely on the

language server support.

that’s all for now!

I haven’t really successfully used an actual web framework for a project before

(right now almost all of my websites are either a single Go binary or static

sites), so I’m interested in seeing how it goes!

There’s still lots for me to learn about, I still haven’t really gotten into

Django’s form validation tooling or authentication systems.

Thanks to Marco Rogers for convincing me to give ORMs a chance.

(we’re still experimenting with the comments-on-Mastodon system! Here are the comments on Mastodon! tell me your favourite Django feature!)

如果可以重来,你还愿意花这段时间读它吗?

· 匿名阅读记录只用于改进推荐

Some notes on starting to use Django | DeepRead