Things I do every time I start a Django project
brntn.me
brntn.me
It incorporates most of these best practices, along with React server side rendering in addition to regular Django templates.
Full disclosure: I'm the creator.
I've seen this pattern a lot recently but haven't figured out what the extra complexity gets you
There's also a _ton_ of preexisting React components you can generally drop in and use, which is less true these days with something like a Django template.
You also have the option of doing SSR and then doing more dynamic stuff on the client side, as a sort of optimization (and plain better user experience than making _more_ server requests to get the initial page state loaded).
Type safety is incredibly important if you're lots of logic in a language, which is why TS is great for SPAs. Does the type safety of TS get you anything if you're just doing SSR with not a whole lot of logic in TS? All of your application logic will be on the Python side of things.
>You also have the option of doing SSR and then doing more dynamic stuff on the client side
Isn't this just the old-school way of doing things before SPAs came around? i.e you render the page on the server and then add dynamics features using JS. I think the new way of doing this is with htmx, hotwire, etc.
The biggest benefit for SSR in my opinion is SEO + first load is fast because its already generated. After that though, its just the plain old SPA experience.
Personally I find JSX to be a terrific templating system, much better than anything like Django's, but if you're familiar with both and prefer Django's, this benefit does not apply to you!
Django templates are perfectly fine as long as you leverage template tags the way they were intended.
Of course there's many ways around this, but doing them in a declarative, type-safe way is not trivial when using Django templates.
Or is it an apples to oranges comparison?
This does make testing a lot easier, as the server response is identical to the hydrated client.
For React, SSR is secondary. For HTMX, it is primary.
See here: https://github.com/silviogutierrez/reactivated/blob/main/dev...
https://github.com/silviogutierrez/reactivated/blob/main/dev...
https://github.com/silviogutierrez/reactivated/blob/main/dev...
> export const Flavor = () => <Select options={flavors} />;
When I read the above, I fear for the new devs. The number of concepts to grasps and the level of parsing and mind bending to do is incredible.
I used to teach code, before arrow functions and React. And I am convinced I would have lost some students to this snippet, especially the "= () =>" segment.
Are we gone too far syntactically for the sake of compactness rather than understandability, allin the name of (fake, IMO) readability?
Also, consider functional languages like Haskell or whatever. Their syntax is exceptionally foreign for users of C-like languages, and so are the concepts. Still, they're (relatively) widely used.
Haskell though requires significantly more work than JS to grasp, for sure.
Could you elaborate on that, please? The way I read this, I could not be further from agreement :)
Maybe we can find consensus by avoiding the extremes.
"Extended code" as you name it is certainly bad with regards to explicitness, while extreme compactness like (some) one liners are as bad as the former but with regards to readability.
Both are negatively impacting understandability.
I think the target market is experienced people who want to use both react and Django, and feel that this project saves time on conceiving and writing their own integration.
One of the reasons perl faded away, imho
For instance, look how blocks are declared in Objective-C: http://fuckingblocksyntax.com/
They are controversial and everyone has different opinions, but I also think this is where programming ligatures come in extremely handy. When => looks more like ⇒ and is even more obviously an arrow, I think that also starts to make it easier to visually "parse" the flow of code like that.
For what it is worth, arrow functions weren't added solely for compactness, but also to fix some historic issues with classic function syntax. (Lexically scoped `this` versus caller scoped `this` being the big one.) A new type of function syntax was desired anyway for those reasons, and the compact syntax was the icing on the cake.
I haven't had the pleasure of teaching such things to students at this point in my career, but I have given a hand to many a junior developer to grasping some of these ideas and I don't think it is that tough, though it can be a shock/surprise if the last JS you touched was many years before. Especially if you are trying to also learn what JSX and/or TSX add on top of all the changes in ES2015+.
The docs site itself: www.reactivated.io . Notice no JS loaded on the client side. It's purely SSR. The code is in the repo under /website.
My personal blog: www.silv.io
And my business: www.joyapp.com
I don't track others that use it, but hopefully they're out there!
EDIT: Looks like the "Concepts" page has what I am looking for. I would add some of that to the front page.
https://docs.djangoproject.com/en/4.0/ref/django-admin/#cmdo...
One minor point on app names. They are really hard/annoying to change once you have production data, because your DB tables will always be appname_modelname, and renaming tables is a real PITA. You can set the model to point to a nonstandard table, but then your project has a confusing non-Djangonic wart that will annoy you forever more. For this reason I think ‘core’ is a safer option, unless you are certain what your app should be named. Naming after one domain model is likely to be too specific. (I strongly recommend against multiple apps until you have functionality you need to commonize between projects, as refactoring models between apps is a nightmare if you get the boundaries wrong.)
Yep, this is what I do. It’s rare that I make anything that can be shared cross-app (most Django apps I make are super simple CRUD-types), so every one of my Django apps has a ‘core’. I also recommend this approach.
<project>
src/
<package>/
models/
__init__.py # Import all model classes (necessary for Django to find them)
some_model.py # Define SomeModel class
views/
__init__.py
some_view.py # Views for SomeModel
settings.py # Add "<package>" to INSTALLED_APPS
urls.py
You still need to register the top level package as an app for Django to find things, but then you don't have to deal with Django's concept of apps beyond that. All your tables will be named <package>_<model> by default, which seems nice.If it turns out later you need resusable "apps" for some reason, you could always add an apps/ subpackage for them.
I haven't tried this in a real project, so I don't know if there are any downsides, but it seems like a decent approach.
I found this article useful while I was experimenting: https://simpleisbetterthancomplex.com/article/2017/08/07/a-m...
There are a few different places where little things break and then you need to use an obscure settings.py variable to fix them, which makes me a little nervous since it will cause a little cognitive friction for Django-fluent developers joining your project. But I do think it's worth experimenting with.
Using Tailwind without a frontend js framework. I needed a way to create lightweight “components” ala React but on the backend, because otherwise you’re either copy pasting classes like mad or (ab)using tailwind’s @apply.
Also, for simpler cases I include partial templates.
This. Exactly this
Go for Jinja2 and don't look back
If there's one defect in Django is the rosy-colored purist view that permeates a lot of its design decisions.
Keeping "logic only in code" made sense in the 90s. And no, I'm not building a new template tag every time I make some stylistic choice.
The need for a custom User model makes me a little sad every time because, well, single `name` fields (rather than `first_name`, `last_name`) and email-for-username do feel to me like more sensible defaults circa 2022.
Am I missing something here?
Or take a look at https://djangopackages.org/ for examples of apps people like to share.
I understand if you want to distribute your app for others to incorporate, but otherwise it felt like the documentation overemphasizes the "app" aspect. It's a reasonable structure but more of a guideline... unless you want to reuse in other codebases
The pitch that you can "reuse" apps across projects always seemed weird to me, because that's basically never something you actually want to do/can do easily without major surgery.
- models
cheese.py
spam.py
__init__.py
You can then put all your cheese related models in cheese.py, and all your spam related models in spam.py. Then Simply import those models from __init__.py and django is none the wiser that anything changes. Tada: organized models without having to dive into the broken mess that is apps.The same trick of course applies to any python file you want to split up. Views, urls, managers, etc etc.
IMO migrations in combinations with apps are fully broken in django. it's unworkable for large projects.
Also, apps override each other in the order or import. E.g one app can override the template of another just by using the same name. This means you can plug AND extend.
It makes the Django CLI comparable to rails. Notably the reset_db and shell_plus command
https://cookiecutter-django.readthedocs.io
I use a modified version of this for all my projects. This one comes with all the goodies
I created this one to create a production ready Django project in few minutes: https://github.com/Mittal-Analytics/django-cookiecutter
Things this does:
- README.md: setup readme with development setup
- Django split settings: split settings for local, testing and production
- Split requirements: split requirements.txt for local and production
- Pre-commit hooks: setup pre-commit hooks for black and pyflakes
- django-envoiron: database config and secrets in environment
- editorconfig: sensible tab/space defaults for html, js and python files
- remote-setup: setup hosting on uberspace
- git push deployment: `git push live` makes the changes live
- github actions for tests: run tests automatically on GithubHonestly I think these should be defaults (or at least configurable options) of the project generator. I guess you could use cookiecutter, but it's not really worth it.
I would also do:
- install django_extensions and django_debug_toolbar
- rename the admin URL route to contain a uuid
- setup black, mypy, pylint, ipdb, ipython, dotenv and doit (I do so for all my python projects)
- manage.py createsuperuser
Also, very often :
- setup celery (locally with fs backend)
- setup vitejs
- install sentry and mailtrap plugins
- install django-allauth
- install DRF
And currently exploring:
- replace DRF with django ninja
I do a lot of Django+DRF projects and built https://apibakery.com/ to help with the initial scaffolding and defining the models (started as my internal tool, later opened it up to the public).
Slow and frustration prone with “sorry this package require packagex version 1 but packagew require it to be 2 now”
Granted, trying to build your own reusable modules for Django is not a great experience. In these cases the tools feels rather restrictive.
"pip install -r requirements.txt"
If you have different requirements, you can use a different file.
Obviously this is only for development, and if you package your Python code properly then you can install the whole damn thing as a package.
I always structures my project like this when start my Django project.
$ mkdir -p my-example-project/src
$ cd my-example-project/src
$ django-admin startproject youtube_downloader .
so all Django related will be under src folder.
1. django-environ 2. celery 3. channels 4. apps structure https://rajasimon.io/blog/django-project-structure/
To setup all the "Hello World" take long time.
That's what I do, complete will all the dependencies I always need (like Celery, Allauth, etc)
It is almost like we can actually build web apps that do more than CRUD.
keep your secrets out of your environment! especially when you aren't providing any additional safety advice like making sure DEBUG is off
How would you avoid that?
Even this article, which recommends keeping your secrets in environment variables, tells you to implement that by storing them in the filesystem. The advice isn't to avoid storing your secrets in the filesystem; it's to avoid storing them in version control.
It is apparently an exercise for the reader to figure out why it's better to read your secrets out of the environment, which read them from a file you provided, than to read them from your own file yourself.
export DATABASE_URL="$(bw get password my_app/db_url/prod)"
And put that in a startup script (that can go in version control).If not, then it's a secret you must manage, and you are back to square one: either using a simpler solution, use a hardware key, or going full secure vault service, with privileged first request, and so on.
For a service, one would need some kind of secret management - but a shell script could set this variable/value for input to eg docker or a k8s setup. Or the service (eg: heroku) could handle it.
If you can call bitwarden from within the python code somehow, such as with subprocess, that would be better.
For the desktop, use the keyring module.
If you start to scale up your threat model, you should use a vault, but the setup is way more costly, and tricky to get the reboot story right (hence the priviledged first requests comments).
I've always accepted this was an attack vector, and some malicious library could extract env vars.
This actually makes a lot of sense, thanks!
- https://diogomonica.com/2017/03/27/why-you-shouldnt-use-env-... - https://blog.forcesunseen.com/stop-storing-secrets-in-enviro...
They both recommend mounting them into a tmpfs, and then unmounting, but I've not yet tried this.
After all, if you have a single server, and the attacker can read a root protected file oe the spawned processes context, you are pwned already. As for exposing env var, popping os.environ is usually enough.
No need to pay for more than you must: bots and script kiddies are not mossad.
1) bring up Django project
2) populate db with example data
3) "Wow auto admin is so cool!
4) Right anyway, let's get to work
5) mkdir my_real_project && cd !! && pip install flask