I have standard Django models with ForeignKey.
Django docs:
"ForeignKey is represented by django.forms.ModelChoiceField, which is a ChoiceField whose choices are a model QuerySet."
and
"If the model field has choices set, then the form field’s widget will be set to Select, with choices coming from the model field’s choices."
Now I have dropdown menu with choices.
I don't want dropdown menu where user can see options. I want CharField(textfield or similar) where user type, but still that must be one of the options from the database for that field. He must type a valid entry.
I tried:
class TransakcijeForm(forms.ModelForm):
model = models.Transakcije
fields = .....
labels = .....
widgets ={'subscriber':forms.TextInput()}
but I receive the message:
"Select a valid choice. That choice is not one of the available choices." (entry is correct and it works with dropdown menu)
This is my first question here and I'm sorry if I miss the form.
CodePudding user response:
The reason you are getting that error is because your form is still treating the subscriber
field as a ModelChoiceField
because you are only overriding what widget is rendered to html. You need to change the actual field type of your field. You can define your form like this:
from django.core.exceptions import ValidationError
class TransakcijeForm(forms.ModelForm):
subscriber = forms.CharField()
class Meta:
model = models.Transakcije
fields = ....
labels = ....
def clean_subscriber(self):
subscriber_id = self.cleaned_data['subscriber']
try:
# adjust this line to appropriately get the model object that you need
subscriber = SubscriberModel.objects.get(id=subscriber_id)
return subscriber
except:
raise ValidationError('Subscriber does not exist')
The line subscriber = forms.CharField()
will change the form to treat the field as a CharField
rather than a ModelChoiceField
. Doing this will cause the form to return the subscriber
field value as a string, so you will need to get the appropriate model object based on the value of the field. That is what the clean_subscriber(self)
function is for. It needs to be named like clean_<field name>()
. That function will take the string that is returned by the form, try and find the correct model object and return it if an object is found. If it finds no matching objects it will raise a ValidationError
so the form doesn't submit with a bad value.