I have a simple foreign key relationship I want to use in a ModelForm, but without a ModelChoiceField.
class Sample(models.Model):
alt = IntegerField(db_index=True, unique=True)
class Assignment(models.Model):
sample = models.ForeignKey(Sample, on_delete=models.CASCADE)
I want to have the AssignmentForm select the sample based on the contents of the sample's alt field. With a ModelChoiceField it would be like this:
class SampleSelect(ModelChoiceField):
def label_from_instance(self, obj):
return obj.alt
class AssignmentForm(ModelForm):
sample = SampleSelect(queryset=Sample.objects.all())
class Meta:
model = Assignment
fields = ['sample']
The ModelChoiceField documentation says to use something else if the number of choices is large.
Allows the selection of a single model object, suitable for representing a foreign key. Note that the default widget for ModelChoiceField becomes impractical when the number of entries increases. You should avoid using it for more than 100 items.
I think I need a custom form field, but I cannot figure out how to do this.
class SampleBAltField(IntegerField):
def clean(self, value):
try:
return Sample.objects.get(alt=value)
except Sample.DoesNotExist:
raise ValidationError(f'Sample with alt {value} does not exist')
This existing code should take an integer from the form and map it back to a foreign key, but I cannot figure out what to override to populate the field for a bound form from the Sample instance.
Is there a relatively easy way to solve this issue with FormFields in the ModelForm, or do I need to write the Form from scratch?