Opened 11 months ago

Closed 11 months ago

Last modified 11 months ago

#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 Mariusz Felisiak, 11 months ago

Component: UncategorizedForms
Resolution: needsinfo
Status: newclosed

Is it not enough to set blank=True to a ForeignKey?

comment:2 by Willem Van Onsem, 11 months 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 David Sanders, 11 months 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 Mariusz Felisiak, 11 months ago

Resolution: needsinfowontfix

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.

Note: See TracTickets for help on using tickets.
Back to Top