Also, it's 2017 and we are still selecting ForeignKeys from an unfiltered drop-down menu with potemtially thousands of entries? This is madness. A PR for using select2.js (https://github.com/django/django/pull/6385) has been floating around for a year now, but progress is glacial.
I fear the admin site code has become so flexible and generic that it's difficult to extend, which is discouraging improvements.
Anyone care to shout out their favourite admin site replacements? I've tried a few but not found a great fit.
This is the same problem I have with most ORM's as well: the easy stuff is easy, and the hard stuff is harder than just doing your own thing (using SQL directly). My solution to this ORM problem and the admin situation is the same: use admin (and ORM) for doing easy things, and don't use it for hard things. It works well!
I've seen a lot of Django codebases where they try to build the whole app around the admin interface, and it's way more trouble than it's worth. Reasonable people could disagree about this, but my stance is to use it for the easy goodness it provides, but get away from it when it starts getting in the way.
With the ORM though there is usually a good reason for why the hard things are hard, and writing your own SQL where needed adds very little friction.
With the admin adding a button to kick off some task should be trivially easy, but for whatever reason involves either using all sorts of terrible hacks that make the codebase completely unreadable, or else creating an entire second admin. That doesn't feel right.
Those two particular customisations should be a lot easier to do, and it might even be something I'll look to implement as a 3rd party library or directly within Django.
My understanding is it's not something they care enough about yet to fix - or it's too hard/expensive.
UPDATE: Also found this blog post from one of the core devs/founders:
This matches my experience. I can't escape the feeling that 90% of that complexity is irrelevant at best, and counterproductive at worst, for my current use-case -- but I haven't quite mustered the bravery to write my own custom admin site for my app.
I wonder if DRF's CoreAPI schemas would make this easier, since you can now auto-generate a JS client for your API models, so you just need to wire up routers and views for your CRUD.
Also, I think the admin traditionally has been a good driving force for feature improvement.
If you have a complicated application then you should be building your own admin interface, with specialised workflows that make it easy for your (admin) users to enter and manipulate the data you wish to manage.
If you want to add a custom action to the instance view of one of your models you have to:
- write a view for your custom action
- override the generated urls for the model admin
- override the template(???) for the admin instance view to
show the action
Considering the Admin itself already has the styling in place to add more custom actions, the main issue is that no one has put in place enough infrastructure to make this easier for people.
(Internally we've written a couple helpers for this, though our way of doing thing relies on internal patterns so might not be great for Django itself)
Eventually we built an actual operations/management/sales interface because Django's admin had too much extra stuff and lacked certain things we wanted to implement, but it wasn't that difficult to put together and it worked well for several months.
The admin is easy; but it's not simple. Behind the simple UI there's a lot of work going on, and a lot of is so that the simple customizations most people work can be done trivially.
Have no shame in making your own templates and views within the admin. That's why it provides those escape hatches.
Django admin is easy to get started with, but a huge pain to extend.
I've always seen the admin as a sort of phpmyadmin. For doing very basic crud.
It's doable. One of the former companies I worked for used to run its entire lead-management-based system on top of a modified 0.96 Django admin, that was ~10 years ago (said company was a mortgage broker). Monkey-patching is a hell of a drug. I'm pretty sure things are way easier to extend now.
In Django, you need to explicitly do some things and that's okay.
from django.db import models
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
indexes = [
Previously, you could indicate you wanted an index on a field, but only on a single field, and you did it in the field definition.
Declaring them in Meta via the Index class is new, as is the multi-field support and direction support. More importantly, you can subclass Index to define other types of indices besides the default (which is btree). For example, Django now ships built-in subclasses to do BRIN and GIN on Postgres.
what about `unique_together` and `index_together`?
A friend also expressed that it might not be worth it to use Django if just for the ORM and migrations (backend is just api), is he right?
Not abnormally big at all if you're writing Python 3 code. The Django team is very good at communicating about planned changes in advance. Aside from dropping Python 2 support, the only reason they're calling it Django 2.0 is because they switched version numbering schemes to a modified version of SemVer.
I would learn now if I were you.
> A friend also expressed that it might not be worth it to use Django if just for the ORM and migrations (backend is just api), is he right?
I'm not sure, because I don't know what the alternatives are for you (I dabble in Django on the side). But I do know that some people do use parts of Django instead of all three layers, so it may not be ridiculous.
Not the sort of thing I recommend unless you have an application that actually needs all of that (which our users do, and if you did I doubt you'd be looking at anything in Python).
I only started using Django about 6 months ago, but I would have started much earlier if I'd known about the incredible built-in admin interface. The built-in user system is also very convenient. I think Django makes a great backend-only system, especially in combination with Django REST framework.
If your code works on 1.11 without warnings, it will work on 2.0 just fine.
"Apart from that Mrs Lincoln, how did you enjoy the play?"
Yes, he is right. If you add The rest framework: http://www.django-rest-framework.org/
you can implement your app all the newest JS frameworks and maintaining a great server environment. You'll have nice debugging tools, a great language and a robust and mature framework.
For those who are curious and don't feel like digging into the release-process documentation, the new system will consist of three point releases per major version. So 2.0, 2.1, 2.2, then 3.0, 3.1, 3.2, and so on.
Each X.2 release will be an LTS. Compatibility policy will be that if you're running X.2, and get no deprecation warnings, you can upgrade direct to (X+1).2 without changing any code. Then when you clear any deprecation warnings that pop up post-upgrade, you're good to go for (X+2).2.
Here's the final summary:
The most breaking part of the the LTS cycle is right _after_ the LTS, so that's the best time to change the major version number.
"This version has been designated as a long-term support (LTS) release, which means that security and data loss fixes will be applied for at least the next three years. It will also receive fixes for crashing bugs, major functionality bugs in newly-introduced features, and regressions from older versions of Django for the next eight months until December 2017"
I expect that something like a "crashing bug" would be something that would be supported in an LTS, but here they're specifically excluding such bugs from the full three year duration. If stability were a priority, I'm not sure I would look at this any differently than an 8 month release.
To be fair, I don't work in this space, so I may have a skewed perspective, but the 8 month limitation items did catch me off guard.
1.8 had a similar timeline (December 2015 limitation), but there were some non security / data-loss bugs fixed in 2016:
Also, Django 1.11 will likely be in Ubuntu 18.04, supported until 2023.
The biggest thing that I disliked about Django was its templating system. Its attempts to magically render values were (and are) offensive. When I looked before, just like Rails, it was take it or leave it, and there was little sympathy for making it pluggable.
Such issues, and the culture's Rails-like resistance to outside suggestion and interoperability, pushed me into Pylons/Pyramid.
Today, I think Django has improved a lot, and I don't think it's fair to continue to lay the pox of being "Rails-for-Python" on it.
Django now supports third-party templating engines (so the dealkiller is gone) and last I checked, the SQLAlchemy integration, while not official, is much better. They now have Python 3 support and as pointed out here, will be going Python 3 exclusive soon.
I've submitted a few bugs and they get triaged quickly. I had a patch or two merged. Pretty happy with that. The Mezzanine guy is also great about this stuff.
Django does follow the old-school big magic model, but I haven't encountered much [recent] trouble in working around that. The community does not seem to respond negatively to such suggestions anymore.
People say it comes down to Ruby v. Python, and I think that's true, but in a different way than most. It comes down to the core culture of Ruby v. Python.
As the MVC framework hype and subsequent noob-influx died down, Django was left with the core Python community of mature hackers who've developed a refined palette for simplicity. This has been Django's biggest asset, and has turned it into something that's worth using today.
Disclaimer here: I was not then, and I am not now, super deeply involved in Django, either the product or the community. This is primarily based on my impressions from light observation and use. Some/much of it could be wrong.
The team that manages Pyramid is extremely competant, I've updated my applications over multiple releases without issues over the years.
I think what people use often depends on weather you prefer to have choices being made for you with tightly coupled systems vs sane defaults that you can customize to your liking.
Templating is the most frequently subbed out part of Django. I'm not sure how you'd make it more "pluggable."
Before you could always call a third-party rendering library, but it usually meant you wouldn't get things like the Django context renderers or template file lookup by default
Also looking at the footer of each site, the Django one screams 'inclusive community' which I think is a positive signal in terms of its future growth.
Personally, as a heavy Python user, I prefer Django's explicitness vs Rails more "magic" style.
By using lighter weight frameworks you're forced to build parts of your own framework in some ways, which can be a bit more work in the short term, but that means it can be optimized for your domain and you can do more to set up explicit boundaries/document how the team should use things. You can also do this in rails/Django, but then you start ignoring the built-in stuff that made them popular in the first place, and there is such a strong idea of "the rails way" that it'll be hard to get buy-in to diverging from that.
OTOH if you're building something that has a pretty moderate scope and aren't worried about it getting too big, both will get the job done fine.
As additional points, rails is also quite a bit slower, and python is honestly a more versatile language than ruby these days (if you want to pull in any ML or scipy code there are obviously a lot more python options).
I've used multiple apps per Django project for grouping and isolating features. The Two Scoops book lays out a nice project architecture for doing this, and some people take it as far as to deploy separate Django apps within the same project as separate services.
Personally i think RoR is the slightly better framework (better defaults, easy test/dev/production setup, sane asset handling), but i prefer Python over Ruby, so i end up using Django.
Edit: What a long strange trip it's been. According to my old bookmarks, wycats developed a rails admin module about 10 years ago (code not available today). I discovered that he also worked on Merb, sort of a fork of Rails, and then after helping to merge that back into Rails, he helped sferik port MerbAdmin to RailsAdmin, which exists today!
I will definitely have to try Rails 5 and see what's up, it looks like I missed a lot over the years.
I would love to know if Django's Admin fares better in this regard.
Sprockets handles minification and cache invalidation for you.
I can speak from personal experience that Sprockets is a PITA if you want to use npm.
Rails' philosophy is "convention over configuration", which means there's a lot of what might be called "magic" and it's less clear how to override defaults.
Django adheres to a more "pythonic" approach in which transparency is valued and it's better to be explicit than implicit. More things are documented and configurable.
While Django does have a certain way it expects you to do things (especially in the sense of where boundaries lie between modules), I find that that's at a higher level of abstraction than Rails, where convention rules down to the level of URL structure.
It's built on top of Django, and makes creating APIs super easy.
It's great to be able to define a DB model, and in a few lines of code have the API endpoint for that DB entity up and running.
When you start getting to complex apps, you may find yourself fighting against the framework somewhat in order to keep your concerns separated, but that's a Hard Problem in general, and so I don't think it's a flaw of the framework itself (though there are a few areas where DRF is opinionated that I think it should not be). If you were using Flask, you'd have more freedom to tweak things when you get to this point, but you'd also have spent 1.5x the dev effort building all of the things that Django/DRF does already.
In short, if you don't know whether you need Django/DRF or Flask, you probably need Django/DRF. Once you have enough experience with Django/DRF to critique that stack's design decisions, you'll be in a position to make good decisions of your own with Flask if Django/DRF doesn't meet your needs.
With Django, would I be able and would it make sense to keep the SQL schema if I changed languages?
Django has the concept of `apps`, where each app gets its own namespace. So for model `foo` in app `app1`, you get a table `app1_foo`. Inside that table it's just the standard SQL columns that you'd expect. So you might need to override the default table name if your new ORM provides one, but no more than that.
The only other piece that might give you grief is the ContentType machinery; there's a content_type table that has a row for each model class, which lets you do generic foreign key lookups. It might be some work to duplicate that, if you start depending on it. But it's not super-complex; it's just <id, app_label, model> in that table.
(My last API was in Go and felt like too much work, even though it worked nicely in the end.)
Once you start adding on features like allowing writes, authentication+authorization, rate limiting, API discovery, client library generation, OAuth support, etc then something like DRF really makes sense.
DRF is pretty darn flexible and it uses Django so you get a lot of functionality for free, including the Django admin if you want a way to explore your data. DRF in no way forces you to use the Django models (or even any models at all).
- We prefer SQLAlchemy to Django's ORM.
- We don't need any templating since we're always returning JSON.
- Django is more of a framework: you plug your code into the appropriate spots. Flask is more of an API: you call it from your own code.
- Django is brilliant... up until the point you want to do something non-Django-y and have to work around a few layers of magic.
I have nothing bad to say about Django and happily use it where it's appropriate. It's not one-size-fits-all, though, and in my experience there are better solutions to some non-HTML-web stuff.
Django+Django Rest Framework are awesome. We do actually use templates for some emails so it's one of the times where it's nice that the template system was ready to go even though the rest of the site is just json.
Some practical improvements in the 3.x line came from the heavy but constructive criticism that Armin Ronacher gave while ensuring that Flask supported Python 3.
I use flyway now for db migrations and what's great is that I can perform migrations in multiple steps (because it's just SQL). So in this case, I can alter table and add a column with nullable, deploy my app to write to both, migrate data at a later time, deploy app again to stop writing to the old column, update column constraints and remove old column.
Does Django ORM have this kind of flexibility?
I don't read the mailing lists but i'm not sure if it's even considered.
If you want async requests today you can take a look at channels: http://channels.readthedocs.io/en/latest/
It's a Vagrant box primarily intended for developing Django itself. It includes Postgres, MySQL, Memcached, Sphinx, Pillow, selenium, and multiple versions of Python.
- django-admin startproject MyProject
- cd MyProject
- python manage.py migrate
- python manage.py runserver
That should give you a very decent development server without requiring VirtualBox or anything like that. I'd recommend following the official tutorial if you want to give it a spin.
There should be something like this for Django with all the "de facto" tech that a dev might need.
The statement: "too many footguns to be used for important projects" is so obviously ridiculous it isn't worthy of a rebuttal.
Regarding (3) testing complex dynamic templates, I don't have much input as I tend to build APIs using Django Rest Framework rather than web apps with Django templates. Perhaps serializers and validators in DRF solve some of your concerns.
(I'd also be curious to hear what frameworks or libraries you've opted to use instead of Django for your use cases.)
I agree intuitive validation is harder. I think it would
be a vast improvement to separate the parts of the
validation that are form-only from the ones that are
actually database constraints, e.g. in a form_validation
kwarg, because in my experience half the problem is that
developers aren't aware of what's happening on the form
vs the database. They could also add some of the validation
that is currently on forms to the database via CHECK
constraints. And they could also do validation in model
setters, not allowing a model attribute to be set to a
value it wouldn't accept via forms.
I have used DRF, and I find the serializers and validators quite easy to work with. My complaint only complaint with DRF is that, at least at the time when I used it 1-2 years ago, it was annoyingly easy to accidentally expose more fields for writing than one intended--in fact my first exposure to it was frantically fixing a bunch of security vulnerabilities I discovered in an API written using it.
For other frameworks, I have used Flask+SQLAlchemy (Core)
and found it a lot better than Django. Like any good
framework grump I am also developing my own, which avoids
all of these problems in exchange for what I'm sure are
a host of problems I haven't considered.