GeometryField does not allow setting blank=True and null=False
|Reported by:||slinkp||Owned by:||nobody|
|Has patch:||yes||Needs documentation:||no|
|Needs tests:||no||Patch needs improvement:||no|
Sometimes you want to populate a required field's missing value with a value generated eg. from other form fields.
One common idiom for doing this is to have SomeField(blank=True, null=False) and provide the missing value in eg. the Form's clean() method.
For example, I've done variations on this a lot:
class Foo(Model): geom = PointField(blank=True, null=False) address = CharField(max_length=100) class Meta: app_label = 'myblock' # or whatever, class FooForm(ModelForm): class Meta: model = Foo def clean(self): geom = self.cleaned_data.get('geom') if not geom: self.cleaned_data['geom'] = geocode(self.cleaned_data['address']) return super(FooForm, self).clean()
But with a GeometryField, that doesn't work, because of these lines in
GeometryField.clean() in django/contrib/gis/forms/fields.py :
if not value: if self.null and not self.required: # The geometry column allows NULL and is not required. return None else: raise forms.ValidationError(self.error_messages['no_geom'])
Effectively, this makes blank=True meaningless.
As far as I know, GeometryField is the only FormField shipped with django that behaves this way.
This is surprising and inconsistent, and leads to odd workarounds to convince forms.GeometryField to leave you alone. Eg. hacking a ModelAdmin's formfield_for_dbfield() like so:
def formfield_for_dbfield(self, db_field, **kwargs): if db_field.name == 'geom': kwargs['required'] = False kwargs['null'] = True return super(MyModelAdmin, self).formfield_for_dbfield(db_field, **kwargs)
Fixing this is trivial. Patch attached.
Change History (7)
Changed 4 years ago by slinkp
comment:1 Changed 4 years ago by aaugustin
- Needs documentation unset
- Needs tests unset
- Patch needs improvement set
- Triage Stage changed from Unreviewed to Accepted