Reputation: 529
The choices variable of one of my fields (django.forms.models.ModelChoiceIterator) in ModelForm contains 3 items. In some cases, I want to use only one of them (the first one in the "list") for the actual HTML.
Here's a part of the Django Python code:
class MyForm(ModelForm):
def __init__(self, *args, user=None, **kwargs):
choices = self.fields['xxx'].choices
qs = choices.queryset
qs = qs[:1]
...
...
self.fields['xxx'] = forms.ChoiceField(
label="xxx",
widget=forms.Select(
attrs={
'class': 'form-select' }
),
self.fields['xxx'].choices = choices
self.fields['xxx'].choices.queryset = qs
class Meta:
...
model = MyModel
fields = ('xxx')
...
This throws an error : 'list' object has no attribute 'queryset'" and, obviously, the size and content of choices do not change.
choices is an instance of django.forms.models.ModelChoiceIterator
How can I reduce the number of items in the choices which will be displayed in the HTML ?
Upvotes: 1
Views: 528
Reputation: 437
It depends. If you want to limit the choices of the field and also apply this limit during validation, you could try something like this:
from django.forms import ModelForm
class MyForm(ModelForm):
def __init__(self, *kargs, **kwargs):
super().__init__(*kargs, **kwargs)
self.fields["xxx"].queryset = self.fields["xxx"].queryset.filter(
pk=self.fields["xxx"].queryset.first().pk
)
You can't use a sliced queryset in this situation, because a sliced queryset cannot be filtered later on during validation.
On the other hand, if you want to limit the choices of the field without affecting validation, you could set the field's iterator to a custom subclass of ModelChoiceIterator
, and then instantiate that field in MyForm
yourself.
from django.forms import ModelForm
from django.forms.models import ModelChoiceField, ModelChoiceIterator
class FirstItemModelChoiceIterator(ModelChoiceIterator):
def __init__(self, field):
self.field = field
self.queryset = field.queryset[:1]
class FirstItemModelChoiceField(ModelChoiceField):
iterator = FirstItemModelChoiceIterator
class MyForm(ModelForm):
xxx = FirstItemModelChoiceField(queryset=...)
The above code doesn't handle the queryset being empty.
Tested on Django 4.2.7.
Upvotes: 0