Django 4.0 release candidate 1 released
djangoproject.com
djangoproject.com
Django gets the shit done. There are plenty of developers to find for it. Lots of good quality plugins. Every problem you have, infrastructure wise, is often already solved and there is a blog post of it.
Its good parts and its bad parts are widely written about. And if that is not enough: the documentation is great.
Great framework to get your product to market, it allows me to focus on building products. I dont want to think about routing forms processing, or project layout again. I want to write code for the product, not for the framework. Django is just good enough. Forms, URL routing and models are not what delivers value to products I am working on. So I don't want to spend time on it.
Remember: no customer cares about your product being run on cool-async-framework-X. Customers just want a good looking and good working product.
Leaving that aside, async is very advisable (even a must) if your backend throws requests against external and potentially blocking services and you want to keep answering your own clients without scaling for no reason.
If you have enough processes/threads running, the CPU scheduler should take care of that , no?
More aptly, if one can throw another physical server at it, is it worth fixing the underlying performance issue?
Sometimes the answer is yes. If you're at a place with even a thousand physical servers running your process and you can save 2% overall performance with a rewrite, that's saving you 20 physical servers worth of performance.
But often the answer is that it's not worth it. That 2% performance increase on a set of 10 servers is not calculable, and more often even a 10% performance benefit is only noticeable on some specific task, not as a constant overhead.
On the other hand, developer time is expensive and can often be best spend on core functionality.
If Django is, let's say even 20% slower than an async framework like FastAPI, but it's going to save three developers a week of development time to implement a feature in Django, then that's probably a much cheaper solution.
I've used Django, Flask, Sanic and FastAPI[1] and today I often choose FastAPI for my projects, but I think Django is still what I'd turn to if I needed to make a full fledged web application quickly, despite its performance not being as good as FastAPI.
[1] Before I learned Django, I also used Zope, and TurboGears.
But yeah, some places have a very expensive acquisition procedure. To the point that the labor in buying expensive things costs more than the thing itself. But those places "solve" the problem by buying large batches, and the hardware x developer costs comparison don't change much.
Moreover, you're right to calculate this per year because maybe you'll throw this entire code away in a year, or maybe it will become the key code for something else, and you'll need to optimize it anyway.
Even sometimes having a meeting to discuss the performance is not cost effective. Six employees around a table for an hour discussing whether or not to improve the performance of 1200€ a year is not cost efficient.
But then again, sometimes it really is. In one environment we were asked to use some tooling on top of the OS that reduced performance by 5%. It was some management toy that would have made the Linux boxes do the same thing as the Windows boxes, but there was a performance penalty of 5%...
5% of 1000 machines is 50 machines, or just over one rack of servers, and so we could go back to management and say "The performance penalty of this is over a rack of machines. Are you sure you want this?" and then they can decide if it's worth it or not.
In the mid 2010s the python web application space felt very stagnant to me, many semi abandoned projects, lots of people leaving for other technologies. But there has been quite some reversal on that since.
I can't grok it completely. All the books that I read on it skipped the architecture part.
Maybe there is a good guide to Django architecture - the big picture?
PS I am rather experienced in Python (Numpy, Pandas, Plotly, Flask, SQLAlchemy, FastAPI, BeautifulSoup are my bread and butter)
The Django file structure, for example, is not exactly optional in Django. Realize FastAPI follows in the footsteps of Flask. Neither FastAPI or Flask are frameworks. As a FastAPI user myself, I do think it’s closer to a happy medium, but it’s nothing remotely comparable to Django.
When using Django, the best advice I have is to dive all the way in. Follow the docs and the best practices first. Besides, manage.py is just like having a well-developed kit of shell scripts/ in your repo.
That is a reasonable price to pay for the batteries included approach.
What I am saying that I do not grok the big picture of Django flow.
For some reason I got up to speed with Laravel much faster and I do not write much PHP.
The books that I skimmed (like recommended Two Scoops of Django) just go into various things you can do but do not show the big picture.
So
appconfig/urls.py depends on
yourapp/views.py which renders html using a template at
yourapp/templates/sometemplate.html
Presuming that you want to interact with the database `yourapp/views.py` probably also depends on models from `yourapp/models.py` or some other apps database model.The small changes in 2.7 were understandable, but quiet a few gems that I used broke in 2.4, and in 2.5. It was a pain to fix, some were never updated.
Much how people complain that changing strings in Python 2->3 hurt adoption; we have had breaking changes that can break gems almost every release.
Ruby is a great language, but Python is so much less stressful, easier to find working libraries, and easier to find jobs. The last reason is likely because of the first two.
It is fine to add things, but when you keep changing the language and breaking things; people hesitate to write software in it. There is a reason the Linux kernel has a rule about (almost) never breaking user-space.
Being able to develop and test standalone HTML components using Storybook is a whole lot nicer than splitting a server-side template into components (which Twig certainly doesn't support cleanly), building a tool to render them and then maintaining your own component library. So normally we end up with HTML bits in Storybook which are copied and pasted into Twig templates, placeholders added and then you can guess they get out of sync.
I appreciate the argument that I should "use JS server-side and render ${js_fe_framework_of_choice} server-side" and it's valid. But I'd also like to be able to run components in _any language_ and get the same DX. Note none of this is talking about hydration - I'm wanting to leverage the JS FE frameworks as clever templating engines which output dumb HTML.
Or is this barking up the wrong tree entirely?
The "problem" is that most of the third-party apps that want to provide templates end up using the default, so either you have to reimplement those or stick with the default engine.
What's stopping you? I use Django Rest Framework to write views and React + Typescript for the front end. Using templates is often way simpler, though.
Django is great. Just don't use its templates or form systems. Indeed react is a great replacement for both.
Templates make it harder to find and debug issues. They have extremely little tooling to give assurances about what they're compiling, whether the syntax is correct etc. This requires you to build massive, flaky test suites.
I'll take react and typescript any day over even one tenth of that.
Either you write big test cases covering everything, or you live with the knowledge that very unexpected things can be passed in to your methods without you getting notified.
And then there's javascript ...
I do prefer working with typescript than with python but I still rather work with Python than with django templates which are way worse.
By contrast, if you have a problem in the python code, the exception stacktrace will point you to exactly where the problem originates. If you add a `breakpoint()` call in the source before the exception point and run the request again, you'll get dropped into a live debugging repl
The tooling is fine and almost always lets you know where you are breaking stuff. Also, comparing react tooling with it is not fair, it is a much modern ecosystem that has pitfalls of its own.
I have been writing Django professionally for 10 years and React + Django together for 4+ years, so I really know what I am talking about here.
It has the downsides you mention (the error reporting is okayish I think). On the other side, you can write html directly (no classname, etc), and there is no transpiling/build tools/server-side rendering to add. String templates are also side-effect free.
For spa I would prefer React (with Typescript): for a request/response old-fashioned app, or something like htmx/hotwire text templates can be very productive. I see your point though.
Edit: extra points.
I haven't used it extensively, so I can't speak how it compares to Django in larger setups.
The answer depends on how you're using react, and what advantages you want to get from it. "How many tools" is not a real question to ask. If you're concerned about ease of development and learning curves, then that gives you an actual goal to optimize for, and it won't coincide with the amount of tools (react is harder to use embedded than with tooling, hence why the latter is more popular).
FastAPI doesn't have those issues at all...
Select yes when asked if you want "custom_bootstrap_compilation"
That will configure a gulp task runner that is capable of manage your javascript dependencies, bundle your CSS/JS, and minify your HTML, CSS, JS and images. You will still need to install npm etc. as described here. You will also need to become familiar with how to install and update Node packages. https://cookiecutter-django.readthedocs.io/en/latest/develop...
- django.core.cache.backends.redis.RedisCache cache backend provides built-in support for caching with Redis
- The runserver management command now supports the --skip-checks option.
- The shell command now respects sys.__interactivehook__ at startup. This allows loading shell history between interactive sessions. As a consequence, readline is no longer loaded if running in isolated mode.
- New QuerySet.contains(obj) method returns whether the queryset contains the given object. This tries to perform the query in the simplest and fastest way possible.
- Lookup expressions may now be used in QuerySet annotations, aggregations, and directly in filters.
I also used a helper library to automatically map namespaced .sql files onto python functions with various return types, which made the development process way more elegant: https://nackjicholson.github.io/aiosql/. Absolute game changer if you plan to go this route - can’t recommend it highly enough.
Right now I have a Flask application with separate dataclass models where I write a function like `get_by_id` and then then query the DB and get a dict back (using psycopg2 with DictRow returns) and then I can pass that directly to the dataclass constructor with `User(**row)`. Very flexible and working really well so far. Not sure how this scales though, but I'm happy with it at the moment.
Pretty good for a new major version release, that's what I call mature software!
I like your spirit! :D
This a a major version increase, looks like very minor new features as usual.
What happended to the async ORM?
At first, everything seemed super easy, but later I hit so many road-blocks that I had to give up (For example defining a self-referential m2m relationship with a custom join table, and getting it working on the admin site).
Don't people really have such problems with it? It really feels like a huge burden when you do things outside the happy-path. Also the documentation is indeed superb but you also hit a lot of outdated info when searching the web.
For instance, in my experience the admin site is best thought of as glorified DB UI. If you need something more than what it can offer out of the box, you should switch to coding it yourself, or live with a quick hack.
I think that most of the time, Django just gets out of the way. At least if you stay away from the inheritance spaghetti that is class-based views. Use the functions, Luke. :)
With Django as soon as I have anything to do with a database I seem to hit this with the ORM. So I start working around it. Next thing you know it all seems to fall apart because of how coupled the rest of the application is to Django's assumptions about views and entities in the DB.
So "You gave up instead of reading the docs.": I go back to flask, or recently FastApi where you have to figure your schemas and access patterns out for yourself in advance instead of building thorough and deep knowledge on how to deactivate parts of Django when they become redundant. Opinion my own, results may vary, IANA your dev, etc
Agreed. My biggest Django headaches ultimately resulted from me trying to make the admin console do more than it's meant to do.
Sure, you easily get into a situation where you're out of luck using the admin module, but there are also entire classes of problems that can be solved using only the build in admin functionality.
If you have a data model that requires a self-referential m2m relationship, think if there is another way to model it ("collection" object), or don't tell Django about it.
Then there's InlineModelAdmin that allows you to integrate your relationships in the admin.
You gave up instead of reading the docs.
You do need to have the documentation handy, and writing efficient queries can be tricky, but it is the ORM that makes the most sense to me, and the easiest to get started with.
Only frustration I have is the power/possibilities of mysql (which I use 99% of the time for various reasons) versus postgre. The latter seems far better and advanced, and it does reflect in the ORM.
But wait, this isn't linked to django, is it? :-)
The one thing I really wish Django had after all these years is multi-column PK support. I bring it up every time I see a thread about Django, hoping the devs or an open-source contributor will take it on. But after 10+ years, the open ticket just keeps passed on and I don't know that I have the skills to do it myself.
Django currently requires that every table have a _single_ primary key column. You can have a unique multi-column index, but you _also_ need to have a single primary key column, which sometimes makes working with existing databases tricky or inefficient.
It's Django's oldest open ticket, from August 2005: https://code.djangoproject.com/ticket/373
The trick is how do you group those columns together in a way that stays compatible with the rest of the framework.
Here's a 2015 proposal "DEP 191" for how to make it work:
- https://github.com/django/deps/blob/main/draft/0191-composit...
Basically, the multi-columns end up needing to be exposed as a single python object (CompositeField) to stay compatible with the rest of the framework, but do changes to the individual "subfields" on the row-object need to be kept in sync (data binding) with the CompositeField-object and maybe vice-versa? Now we need an "Observer" (which Django doesn't currently have) to watch for changes to fields, etc. So a lot of new concepts end up needing to be introduced to make this happen. And it needs to work with migrations and serialization while trying to maintain backward-compatibility.
Here's rough code (again, from 2015):
https://github.com/django/django/pull/4553
Since 2015, Django now has class-based-indexes which should make things slightly easier:
https://docs.djangoproject.com/en/stable/ref/models/indexes/
Maybe at least the Observables could get merged in as a first-step which would make the remaining work a little easier?
Django Admin is not really designed to be an all-encompassing admin solution I've found, it's a good start but normally you design your own admin console anyway using your API so I've not cared that much about those shortcomings.
With Entity Framework and Dapper, I don't think I can be more productive at the back-end in any other stack than I'm with .NET. If I have a couple of models, I'm usually done with basic CRUD, including REST controllers under an hour.
For the front-end, I wrote a couple of purpose-built generators for now.
That being said, weighing up the good with the bad, its still my favourite web framework
It obviously depends very much on your opinion on what defines "heavy processing", but we do all those things without too much trouble. Obviously we may, and probably do, do things differently to you (we dont use Angular for example, though that seems like it wouldnt be too big a factor) so YMMV, but yeh, for us its been pretty solid
I did follow the docs, it gave errors for one reason after another, and I don't have the time to dive into Django internals anymore when stuff like that keeps happening. From there came my opinion that non-happy path is not very much supported.
I never got the chance to use it professionally so I didn’t get the “fully under control” feeling I get when working with .NET, thus never had the confidence to push for it in my company/clients out of fear of not being able to fix whatever went wrong.
Kind of regretting not making the switch back then, but well, nowadays .NET is good enough. Never managed to squeeze as much productivity as I did with those small college projects back then.
For beginners, there are much better alternatives and, frankly, Django way of development is severely restricting.
Starting off with an API backend and a React/Angular/Vue front end, allows new developers to learn better abstractions (and not merge front ends and back-ends)
The very idea of "sending UI code to the front end for every request" is unsuitable for medium to large projects. But, if you start building smaller projects with an vertically integrated system like Django, it becomes increasingly difficult to think about larger projects.
Are they any other beginner alternatives I should be looking at ?
Once you move on to using Django (probably with REST Framework) for the backend and React or some other JS framework for the front-end, you get some slightly difficult things involving Auth and some other stuff, and of course you can take the complexity as far as you want and I'm sure there are some Django devs with 10-15 years of experience who are experts in parts of the framework that I'm not even aware of, but I don't think learning Django to the point where you can ship a reasonably competent app is more difficult than learning Node/Express, or Rails, or whatever.
Again, question of taste :)