#28107: Can't perform annotation on related table when relation between tables
not
on primary key
-------------------------------------+-------------------------------------
Reporter: | Owner: nobody
powderflask |
Type: | Status: new
Uncategorized |
Component: Database | Version: 1.11
layer (models, ORM) |
Severity: Normal | Keywords: QuerySet.extra
Triage Stage: | Has patch: 0
Unreviewed |
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------------------------+-------------------------------------
I'm working with a legacy DB (ArcSDE database -- really ugly) -- have been
able to accommodate its oddities without resorting much to raw SQL, but
django upgrade (1.8 --> 1.11) caused a previously working annotation to
fail:
{{{ psycopg2.ProgrammingError: :column ... must appear in the GROUP BY
clause or be used in an aggregate function }}}
**DB: PostgreSQL 9.3.16 ** (i.e., this is not same issue as #26758 )
Python3.6, Django1.11
The annotation simply counts the number of related records from a related
'attachments' table:
{{{ qs.annotate(num_attachments=Count('attachments')) }}}
The root cause appears to be that the relation between the model and
attachments tables uses a unique field ''other than the main model's
primary key'' (I know -- told you it was ugly - ArcSDE does not really
support relations, except they implement attachments with this odd ball **
sigh **).
The change in behaviour seems to manifest from #19259 (I believe django1.8
added all fields to the groupby clause).
Since django now includes only the primary key in the groupby clause,
postgresql won't do this aggregation across a relation that uses a non-pk
field.
I suspect there is a general issue here that aggregations on a related-
table won't work in postgresql unless the relation is on the primary key
field (so, yeah, basically this issue applies to almost no one, right...).
Seems likely there is a better solution to this, but after a half-day of
search / effort, I resorted to the following:
{{{
qs.extra(select={'num_attachments':
'SELECT COUNT("attachmentid") FROM {attach_table} WHERE
{attach_table}.rel_globalid = {model_table}.globalid'.format(
model_table = qs.model._meta.db_table,
attach_table =
qs.model.AttachmentModel._meta.db_table,
)},)
}}}
This works and achieves my goal -- to annotate model with the number of
related attachments.
Since the {{{ model.attachments.count() }}} query works just fine, I'm
considering eliminating this annotation and replacing with a property on
the model class, what's one more query... I'm sure there must be an
smoother way, but it eludes me...
Since the docs suggested to open a ticket for queries that could not be
resolved without resorting to extra(), here it is, for whatever its worth.
Hope this hasn't been a complete waste of time for you.
--
Ticket URL: <https://code.djangoproject.com/ticket/28107>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/054.468d29500601a42674d1df5c30c72119%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.