#33792: Using QuerySet.extra works while RawSQL inside annotate fails
-------------------------------------+-------------------------------------
Reporter: Shane | Owner: nobody
Ambler |
Type: | Status: new
Uncategorized |
Component: Database | Version: 4.0
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 |
-------------------------------------+-------------------------------------
Starting with a simplified model like this
{{{#!python
class Materials(models.Model):
title = models.TextField()
class Quotes(models.Model):
source = models.ForeignKey('Materials', on_delete=models.CASCADE)
quote = models.TextField()
}}}
I then create a form -
{{{#!python
class QuoteForm(forms.Form):
source =
forms.ModelChoiceField(queryset=Materials.objects.order_by('title').all())
quote = forms.CharField(widget=forms.Textarea())
def clean_source(self):
print('Cleaning source:', self.cleaned_data)
return self.cleaned_data['source']
}}}
At this point, all works well, but the `title` often starts with a numeric
string and I want to change the sort order so that `2nd congress` sorts
before `12th congress`.
Using postgresql, I can change the `source` line to
{{{#!python
source =
forms.ModelChoiceField(queryset=Materials.objects.annotate(num_order=RawSQL('''cast(substring(title
from '^([0-9]{1,10})') as integer)''',
('',))).order_by('num_order','title'))
}}}
and this provides the forms select list sorted the way I want but the form
fails to validate with source being an invalid choice. I added the
`clean_source()` method above to also indicate that using `RawSQL` here
fails to call the `clean_source` method.
If I change the source line to use `QuerySet.extra()` -
{{{#!python
source =
forms.ModelChoiceField(queryset=Materials.objects.extra(select={'num_order':
'''cast(substring(title from '^([0-9]{1,10})') as
integer)'''}).order_by('num_order','title'))
}}}
I get the sort order, form validation works and `clean_source()` gets
called.
--
Ticket URL: <https://code.djangoproject.com/ticket/33792>
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 view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/01070181801008ef-64a0345c-5783-4817-9c55-08a6eabdeb54-000000%40eu-central-1.amazonses.com.