Opened 3 years ago
Closed 3 years ago
#33114 closed Cleanup/optimization (fixed)
StringAgg() should set output_field to TextField.
Reported by: | Swen Kooij | Owned by: | ali sayyah |
---|---|---|---|
Component: | contrib.postgres | Version: | 3.2 |
Severity: | Normal | Keywords: | |
Cc: | Simon Charette | Triage Stage: | Ready for checkin |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Example:
class MyModel(models.Model): name = models.TextField() list(MyModel.objects.annotate(names=StringAgg('name', ',')))
Results in the error:
django.core.exceptions.FieldError: Expression contains mixed types: TextField, CharField. You must set output_field.
There are two possible work-arounds:
- Derive from
StringAgg
and set theoutput_field
:
class TextStringAgg(StringAgg): output_field = TextField()
- Wrap the expression in
ExpressionWrapper
:
ExpressionWrapper(StringAgg('name', ','), output_field=TextField())
This seems to be a regression introduced in 3.2 as part of this change: https://github.com/django/django/commit/1e38f1191de21b6e96736f58df57dfb851a28c1f
Change History (13)
comment:1 by , 3 years ago
Cc: | added |
---|
comment:2 by , 3 years ago
Sorry, I didn't quite grasp from that part of the release notes that this is expected.
Setting a default output_field
on StringAgg
would help. It would restore the original behaviour. It's a bit strange to get this error when dealing with strings. Whether it's a CharField
or TextField
, you still end up with a string in Python. Having to explicitly add an output_field
for StringAgg
seems to be just an annoyance.
follow-up: 4 comment:3 by , 3 years ago
This will be an issue for all expressions that accept mixed string types.
Since PostgreSQL documents that string_agg ( value text, delimiter text ) → text
I guess we should default to output_field = models.TextField()
to limit this annoyance.
comment:4 by , 3 years ago
Summary: | StringAgg always fails on TextField → StringAgg() should set output_field to TextField. |
---|---|
Triage Stage: | Unreviewed → Accepted |
Type: | Uncategorized → Cleanup/optimization |
Replying to Simon Charette:
This will be an issue for all expressions that accept mixed string types.
Since PostgreSQL documents that
string_agg ( value text, delimiter text ) → text
I guess we should default tooutput_field = models.TextField()
to limit this annoyance.
OK, agreed. Swen, would you like to prepare a patch (with tests)?
comment:5 by , 3 years ago
Component: | Database layer (models, ORM) → contrib.postgres |
---|
comment:6 by , 3 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
follow-up: 9 comment:8 by , 3 years ago
main branch (which will target 4.1, now that 4.0 is feature frozen).
comment:9 by , 3 years ago
Replying to Claude Paroz:
main branch (which will target 4.1, now that 4.0 is feature frozen).
Thank you.
comment:10 by , 3 years ago
Has patch: | set |
---|
comment:11 by , 3 years ago
PR with the fix and a unittest: https://github.com/django/django/pull/14898
comment:12 by , 3 years ago
Triage Stage: | Accepted → Ready for checkin |
---|
This side-effect is documented, see 9369f0cebba1f65909a14dec6aa3515ec1eb2557 and #31967. Also, you can set
output_field
directly in theStringAgg()
, e.g.I'm not sure if there is anything specific that we could do.