One argument of the core devs in the ticket is that extra is a bad thing to have, only there because it was there before raw() came. I think that this is wrong, for example when you want to have all the power of the filters and the sortings but still be able to make complex queries that the ORM can't handle in a decent time.
And I think that the ability to add join to extra would be a great plus. For example in the admin, you may want to display the number of foreign keys for each row, and eventually, two different counts. Two counts as annotate returns wrong results, where as the possibility to add something like the following resolves the problem and reduces dramatically the query time (by factor 120 in my case).
LEFT OUTER JOIN (SELECT COUNT(*) AS "devices_count", "accounts_venuedevice"."venue_id" FROM "accounts_venuedevice" WHERE "accounts_venuedevice"."enabled"=true GROUP BY "accounts_venuedevice"."venue_id" ) AS "enabled_devices" ON ( "accounts_venue"."id" = "enabled_devices"."venue_id")
On the other hand, having to add the filters and the sorting by hand to the RawQuerySet is a pain in the ass.
Even if extra joins shouldn't be used for production code, it could be very helpful for some edge-cases like for the admin interface.
The short answer to this -- if you think this is easy, go ahead and produce a patch. There's a reason we haven't done this.
The longer answer:
The core team's position on extra() doesn't exist because we've got some sort of theoretical purity that we want to maintain. It's come as a result of *many* years wrestling with a concept that, at it's core, is badly formed. extra() has been the cause of more headaches and sleepless nights on my part than I care to count. If I could kill it with fire, I would.
As I indicated in a different thread about Marc Tamlyn's Kickstarter project -- Django's ORM is very deliberately *not* a SQL generation engine. When we talk about aggregates, we don't talk about "GROUP BY" clauses - we are expressing the idea of building an average/sum/etc over a group of objects. When we talk about related objects, we talk about filtering related object, not the construction of JOIN clauses.
This is a deliberate decision. Django's ORM is designed to make 90% of common SQL queries easy to generate. It also had the original idea that it should be possible to express *non* SQL queries as well - although this hasn't actually manifested in practice.
Django's ORM *does not* have "join", "group by", "having" or other SQL-specific API endpoints -- and it won't gain them without a *massive* shift occurring in the fundamental design of the ORM.
I'm not saying that JOIN etc clauses aren't useful - I'm saying it's a deliberate design decision of Django's ORM to *not* support that use case.
If you're looking at a problem, and thinking "I need a LEFT OUTER JOIN", then the answer to your problem is raw SQL, not to introduce SQL concepts into Django's ORM. Alternatively, use an ORM that *does* give first-class representation of SQL concepts, like SQLAlchemy.
Yours,
Russ Magee %-)