Comment by senko

Comment by senko 4 days ago

13 replies

Some more Django recommendations from Frank Wiles of Revsys (Django consultancy): https://frankwiles.com/questions/starting-django-projects/

I'll add a few of my own:

* Set up the project using uv

* I name the django project "project"; so settings are project/settings.py, main urls are project/urls.py, etc

* I always define a custom Django user model even if I don't need anything extra yet; easier to expand later

* settings.py actually conflates project config (Django apps, middleware, etc) and instance/environment config (Database access, storages, email, auth...); I hardcode the project config (since that doesn't change between environemnts) and use python-dotenv to pull settings from environment / .env; I document all such configurable vars in .env.example, and the defaults are sane for local/dev setup (such as DEBUG=true, SQLIte database, ALLOWED_HOSTS=*, and a randomly-generated SECRET_KEY); oh and I use dj-database-url to use DATABASE_URL (defaults to sqlite:///sqlite.db)

* I immediately set up up ruff, ty, pytest, pre-commit hook and GH workflow to run ruff/ty/pytest

Previously I had elaborate scaffolding/skeleton templates, or nowadays a small shell script and I tell Claude to adapt settings.py as per above instructions :)

bodge5000 4 days ago

I'll add one; Add shell_plus. It makes the django shell so much nicer to use, especially on larger projects (mostly because it auto-imports all your models). IIRC, it involves adding ipython and django_extensions as a dependency, and then adding django-extensions (annoyingly, note that the underscore changes to a dash, this trips me up everytime I add it) to your installed apps.

Saying that, I'm sure django-extensions does a lot more than shell_plus but I've never actually explored what those extra features are, so think I'll do that now

Edit: Turns out you can use bpython, ptpython or none at all with shell_plus, so good to know if you prefer any of them to ipython

  • el_io 4 days ago

    > mostly because it auto-imports all your models

    Django does this by default now. Since 5.0 if I'm remembering it correctly.

    • anticodon 3 days ago

      shell_plus is still superior because it also imports other useful stuff and allows adding custom list of additional imports.

      Also, shell_plus has --print-sql option for easy construction and debugging of ORM queries.

    • bodge5000 4 days ago

      In the default shell? I've definitely started new django projects since 2023 and I seem to remember always having to use shell_plus for that, though maybe thats just become something I automatically add without thinking

      Edit: Yep, you're right, wow thats pretty big for me

Izkata 4 days ago

> * settings.py actually conflates project config (Django apps, middleware, etc) and instance/environment config (Database access, storages, email, auth...); I hardcode the project config (since that doesn't change between environemnts) and use python-dotenv to pull settings from environment / .env; I document all such configurable vars in .env.example, and the defaults are sane for local/dev setup (such as DEBUG=true, SQLIte database, ALLOWED_HOSTS=*, and a randomly-generated SECRET_KEY); oh and I use dj-database-url to use DATABASE_URL (defaults to sqlite:///sqlite.db)

There is a convention to create "foo_settings.py" for different environments next to "settings.py" and start it with "from .settings import *"

You'll still want something else for secrets, but this works well for everything else, including sane defaults with overrides (like DEBUG=False in the base and True in only the appropriate ones).

  • seabrookmx 4 days ago

    IMO this is an antipattern because having a python file for each environment means you have bespoke code for each environment that is difficult to test and easily diverges from each other.

    If you use OP's way (I do something similar using pydantic-settings) the only thing that changes is your environment vars, which are much easier to reason about.

seabrookmx 4 days ago

I've been really enjoying ruff/ty on my non-Django projects. Was there anything special you had to do to make ty play nice with Django? I kind of assumed with how dynamic a lot of its functionality is ty would just throw a type error for every Model.objects.whatever call.

graemep 4 days ago

> use python-dotenv to pull settings from environment / .env

I disagree strongly with this one. All you are doing is moving those settings to a different file. You might as well use a local settings file that reads the common settings.

On production keep things like API keys that need to be kept secret elsewhere - as a minimum outside the project directories and owned by a different user.

  • senko 4 days ago

    Sure, that works as well, for example on some deploys I set the settings in systemd service file. However, it's more convenient to just have .env right there.

    > On production keep things like API keys that need to be kept secret elsewhere - as a minimum outside the project directories and owned by a different user.

    Curious what extra protection this gives you, considering the environment variables are, well, in the environment, and can be read by process. If someone does a remote code execution attack on the server, they can just read the environment.

    The only thing I can imagine it does protect is if you mistakenly expose project root folder on the web server.

    • Quothling 3 days ago

      > Curious what extra protection this gives you, considering the environment variables are, well, in the environment, and can be read by process. If someone does a remote code execution attack on the server, they can just read the environment.

      While your secrets are available at runtime, you get a lot of governance by placing them in something like a keyault. You get an audit trail, you can setup rotation policies. It's easier to reference different secrets for dev, test, prod etc. I'd argue that there is a lot of added security in the fact that your developers won't actually need any sort of access to a secret stored in a keyvault, especially because you don't need to give developers access to runtime logs or even the production envrionment at all. You're right that it's not a perfect way to protect a secret of course.

    • graemep 3 days ago

      > Curious what extra protection this gives you, considering the environment variables are, well, in the environment, and can be read by process.

      Look at it this way. What does putting things in a .env file get you over putting them in a local settings file? Both are readable by any process running as a user that can read those files, both are within the project directory and might be accidentally committed.

      It also makes it easier to have a setup where secrets cannot be read by other software - e.g. this: https://www.theregister.com/2026/01/28/claude_code_ai_secret...

  • advisedwang 4 days ago

    That's something that python-dotenv enables. It can pull from environment, which you can wire up from k8s secrets or whatever is the case for your hosting.

Quothling 3 days ago

> use python-dotenv

If you're using UV why would you not use uv.env instead?