[Django] #28072: Cannot annotate exisiting field

11 views
Skip to first unread message

Django

unread,
Apr 12, 2017, 9:34:17 AM4/12/17
to django-...@googlegroups.com
#28072: Cannot annotate exisiting field
-------------------------------------+-------------------------------------
Reporter: Marcin | Owner: nobody
Nowak |
Type: Bug | Status: new
Component: Database | Version: 1.8
layer (models, ORM) |
Severity: Normal | Keywords:
Triage Stage: | Has patch: 0
Unreviewed |
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------------------------+-------------------------------------
Because of this exception
https://github.com/django/django/blob/master/django/db/models/query.py#L900
I can't add annotation.
I need to >rename< db_field within the query and fetch results by
.values() / .values_list(), so mapping db values to fields is not
required.

Queries like "select x as y, y as x from table" are valid, and as a Django
user I want to do similar things using queryset API, for my own
responsibility.

Please add possibility to bypass the constraint somehow, or move this
constraint elsewhere and activiate it when no .values()/.values_list() are
used. Also please backport the change to the 1.8.x branch.

Thank you.

--
Ticket URL: <https://code.djangoproject.com/ticket/28072>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Apr 12, 2017, 9:44:21 AM4/12/17
to django-...@googlegroups.com
#28072: Allow QuerySet.annotate() to use the name of an exisiting field
-------------------------------------+-------------------------------------
Reporter: Marcin Nowak | Owner: nobody
Type: New feature | Status: new
Component: Database layer | Version: 1.8
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Tim Graham):

* type: Bug => New feature
* stage: Unreviewed => Accepted


Comment:

I'm not sure if this is feasible or a good idea, but if you provide a
patch, we can take a look. Per our
[https://docs.djangoproject.com/en/dev/internals/security/#supported-
versions supported versions policy], it won't be backported to 1.8.

--
Ticket URL: <https://code.djangoproject.com/ticket/28072#comment:1>

Django

unread,
Apr 13, 2017, 10:48:10 AM4/13/17
to django-...@googlegroups.com
#28072: Allow QuerySet.annotate() to use the name of an exisiting field
-------------------------------------+-------------------------------------

Reporter: Marcin Nowak | Owner: nobody
Type: New feature | Status: new
Component: Database layer | Version: 1.8
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Marcin Nowak):

Please note that `.extra(select={'x': 'y'})` works without limitation and
can be used as a workaround for `.annotate()`'s conflict exception.

--
Ticket URL: <https://code.djangoproject.com/ticket/28072#comment:2>

Django

unread,
Feb 14, 2020, 3:49:05 PM2/14/20
to django-...@googlegroups.com
#28072: Allow QuerySet.annotate() to use the name of an exisiting field
-------------------------------------+-------------------------------------

Reporter: Marcin Nowak | Owner: nobody
Type: New feature | Status: new
Component: Database layer | Version: 1.8
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Marcin Nowak):

Thank you. But please note that there is no possibility to use expressions
with extra(select={..}).

--
Ticket URL: <https://code.djangoproject.com/ticket/28072#comment:3>

Django

unread,
Aug 6, 2022, 11:47:28 AM8/6/22
to django-...@googlegroups.com
#28072: Allow QuerySet.annotate() to use the name of an exisiting field
-------------------------------------+-------------------------------------

Reporter: Marcin Nowak | Owner: nobody
Type: New feature | Status: new
Component: Database layer | Version: 1.8
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Evan Fiddler):

Is there still interest from anyone else on this? I accomplished this is
an abstracted version of QuerySet that my company uses internally.
Approved to make a PR against Django Project if there’s interest.

The one main concern I have on this idea is in two parts:
1. In order to successfully annotate the queryset with a name that’s
already used (and for it to be at all useful) the original value must be
removed from the queryset.
2. This is very doable by pulling current values, removing the “old” key,
then applying the annotate to the queryset. All very doable.

However, this returns an **incredibly** unsafe queryset which if we see in
anything but a read-only way could overwrite data in the model/db.

So, here’s my solution: make ANOTHER method (`annotate_override()` or
`annotate_read_only()`or something like that) that returns the annotated
queryset with the old name/value removed and the passed-in expression
annotated.

One issue I see with this is that it’s returning a true queryset and
therefore, in order for THIS to work well, we may need another abstracted
class on `QuerySet` like `ReadOnlyQuerySet(QuerySet)` or something like
that…which makes this a much larger change.

Alternatively, the doc string on this new method could be incredibly
verbose with warnings about usage.

Lastly, we could just provide a k, v param to `annotate()` (e.g.
`annotate(<annotation expression>, override_model=True)` and the change is
smaller but less safe.

If this sound good, I’ll assign and make the PR. I’d like some feedback on
this first though.

--
Ticket URL: <https://code.djangoproject.com/ticket/28072#comment:5>

Django

unread,
Aug 11, 2022, 3:12:08 AM8/11/22
to django-...@googlegroups.com
#28072: Allow QuerySet.annotate() to use the name of an exisiting field
-------------------------------------+-------------------------------------

Reporter: Marcin Nowak | Owner: nobody
Type: New feature | Status: new
Component: Database layer | Version: 1.8
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Alexander3):

I'm interested, I sometimes need things like: `qs =
qs.annotate(sales=F('sales') * F("price"))` and for me it's only readonly
usecase.
I can work around it with `qs.values().annotate()` maybe this is more
clean approach.

--
Ticket URL: <https://code.djangoproject.com/ticket/28072#comment:6>

Reply all
Reply to author
Forward
0 new messages