#34635 closed Uncategorized (wontfix)
ModelChoiceField with a to_attr that can have an EMPTY_VALUE
| Reported by: | Willem Van Onsem | Owned by: | nobody |
|---|---|---|---|
| Component: | Forms | Version: | 4.2 |
| Severity: | Normal | Keywords: | |
| Cc: | Triage Stage: | Unreviewed | |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
Recently a person asked this question on [StackOverflow](https://stackoverflow.com/questions/76409430/django-testing-a-simple-model-with-foreign-key-and-updateview/76409867). Imagine we have the following models:
from django.db import models
class Location(models.Model):
location_number = models.CharField(max_length=30, unique=True)
name = models.CharField(max_length=128)
class Project(models.Model):
location = models.ForeignKey(Location, on_delete=models.CASCADE, to_field='location_number', db_column='location_number', related_name='projects', verbose_name='Standort')
Then it is possible to construct a Location with an empty string for location_number:
Location.objects.create(location_number='', name='location_name')
But now if we construct a ModelForm, it will not accept this as valid option, indeed:
class ProjectForm(forms.ModelForm):
class Meta:
model = Project
fields = ['location']
This will render a <select> with the values of the to_field as values, so:
<select name="location"> <option value="">location_name</option> </select>
now if the form is submitted, it will pass the empty string for location, but the form field will reject it because the field is required, and it sees this as an empty value.
The problem is thus a bit of a mismatch between what a form does and the possible values of a model. Unfortunately I don't see an easy solution for this. Perhaps the checks framework can at least warn if a ForeignKey refers to a CharField or another field that can have an empty value.
Change History (4)
comment:1 by , 2 years ago
| Component: | Uncategorized → Forms |
|---|---|
| Resolution: | → needsinfo |
| Status: | new → closed |
comment:2 by , 2 years ago
Yes, but that seems counterintuitive, since it seems to suggest that you leave the *reference* blank, we here leave the location_id blank, but the form definitely refers to a Location. So it seems counterintuitive, and misleading.
comment:3 by , 2 years ago
imho this is exactly what blank is for :P https://docs.djangoproject.com/en/4.2/ref/models/fields/#blank
If True, the field is allowed to be blank … Note that this is different than null. null is purely database-related, whereas blank is validation-related. If a field has blank=True, form validation will allow entry of an empty value.
The key here is that "" is an empty value. blank=True is declaring that empty values are permissible.
since it seems to suggest that you leave the *reference* blank
Are you referring to null/None ? 🤔
So it seems counterintuitive, and misleading.
And so the NULL debate rages on 😅
comment:4 by , 2 years ago
| Resolution: | needsinfo → wontfix |
|---|
Yes, ...
Great, so it works as documented. That's why we have blank.
... but that seems counterintuitive
We had this debate so many times, we cannot change the long standing behavior for an edge case of blank primary keys. TBH, I don't find it misleading that you have to set blank=True to allow for blank foreign keys.
You can start a discussion on DevelopersMailingList if you don't agree, however, I don't think there would be consensus to change the current behavior.
Is it not enough to set
blank=Trueto aForeignKey?