Django:点没有从 ModelForm clean 传递到 Model clean
Django: Point not passing from ModelForm clean to Model clean
我有一个 Occurrence
模型,我将其作为 TabularInline
放在另一个模型的管理页面上。它有一个 PointField
和一个 PolygonField
,其中至少有一个必须存在。
这是模型的一部分:
class Occurrence(models.Model):
name = models.CharField(max_length=254)
location = models.PointField(null=True, blank=True)
bounding_polygon = models.PolygonField(null=True, blank=True)
def clean(self):
# Checks if at least one of the spatial fields is filled in
if not self.location and not self.bounding_polygon:
raise ValidationError('At least one of the spatial fields (point or polygon) is required.')
在 TabularInline
中,我想放置 name
和 location
,但是当我添加新行时,location
的地图不会出现。为了解决这个问题,我使用了一种可以输入纬度和经度的表格,然后将其转换为 location
的 Point
。
这是我的表格:
class OccurrenceForm(forms.ModelForm):
latitude = forms.FloatField(
min_value=-90,
max_value=90,
required=False,
help_text="Enter coordinates as an alternative to selecting a point on the map."
)
longitude = forms.FloatField(
min_value=-180,
max_value=180,
required=False,
)
class Meta(object):
model = Occurrence
exclude = []
def __init__(self, *args, **kwargs):
super(OccurrenceForm, self).__init__(*args, **kwargs)
coordinates = self.initial.get("location", None)
if isinstance(coordinates, Point):
self.initial["longitude"], self.initial["latitude"] = coordinates.tuple
def clean(self):
data = super(OccurrenceForm, self).clean()
#if "latitude" in self.changed_data or "longitude" in self.changed_data:
lat, lng = data.pop("latitude", None), data.pop("longitude", None)
if lat and lng:
data["location"] = Point(lng, lat, srid=4326)
return data
这是我的 TabularInline 模型:
class OccurrencesInline(admin.TabularInline):
model = Occurrence
fields = ('name', 'latitude', 'longitude')
show_change_link = True
extra = 1
form = OccurrenceForm
但是,在 ModelForm
中为 location
创建的 Point
不会传递给 Model
clean
。
我已经在 TabularInline
中测试了相同的 ModelForm
并且它没有问题。
有人知道为什么会这样吗?
我会 post 解决方案,因为它可能对某人有用。
问题是我没有把模型中定义的PointField
放到OccurrencesInline
中定义的fields
中。
解决方案是添加该字段,但由于我不希望它可见,所以我使用 forms.HiddenInput
.
隐藏了它
class OccurrencesInline(admin.TabularInline):
model = Occurrence
fields = ('name', 'latitude', 'longitude', 'location')
show_change_link = True
extra = 1
formset = AtLeastOneFormSet
form = OccurrenceForm
formfield_overrides = {
models.PointField: {'widget': forms.HiddenInput()},
}
我有一个 Occurrence
模型,我将其作为 TabularInline
放在另一个模型的管理页面上。它有一个 PointField
和一个 PolygonField
,其中至少有一个必须存在。
这是模型的一部分:
class Occurrence(models.Model):
name = models.CharField(max_length=254)
location = models.PointField(null=True, blank=True)
bounding_polygon = models.PolygonField(null=True, blank=True)
def clean(self):
# Checks if at least one of the spatial fields is filled in
if not self.location and not self.bounding_polygon:
raise ValidationError('At least one of the spatial fields (point or polygon) is required.')
在 TabularInline
中,我想放置 name
和 location
,但是当我添加新行时,location
的地图不会出现。为了解决这个问题,我使用了一种可以输入纬度和经度的表格,然后将其转换为 location
的 Point
。
这是我的表格:
class OccurrenceForm(forms.ModelForm):
latitude = forms.FloatField(
min_value=-90,
max_value=90,
required=False,
help_text="Enter coordinates as an alternative to selecting a point on the map."
)
longitude = forms.FloatField(
min_value=-180,
max_value=180,
required=False,
)
class Meta(object):
model = Occurrence
exclude = []
def __init__(self, *args, **kwargs):
super(OccurrenceForm, self).__init__(*args, **kwargs)
coordinates = self.initial.get("location", None)
if isinstance(coordinates, Point):
self.initial["longitude"], self.initial["latitude"] = coordinates.tuple
def clean(self):
data = super(OccurrenceForm, self).clean()
#if "latitude" in self.changed_data or "longitude" in self.changed_data:
lat, lng = data.pop("latitude", None), data.pop("longitude", None)
if lat and lng:
data["location"] = Point(lng, lat, srid=4326)
return data
这是我的 TabularInline 模型:
class OccurrencesInline(admin.TabularInline):
model = Occurrence
fields = ('name', 'latitude', 'longitude')
show_change_link = True
extra = 1
form = OccurrenceForm
但是,在 ModelForm
中为 location
创建的 Point
不会传递给 Model
clean
。
我已经在 TabularInline
中测试了相同的 ModelForm
并且它没有问题。
有人知道为什么会这样吗?
我会 post 解决方案,因为它可能对某人有用。
问题是我没有把模型中定义的PointField
放到OccurrencesInline
中定义的fields
中。
解决方案是添加该字段,但由于我不希望它可见,所以我使用 forms.HiddenInput
.
class OccurrencesInline(admin.TabularInline):
model = Occurrence
fields = ('name', 'latitude', 'longitude', 'location')
show_change_link = True
extra = 1
formset = AtLeastOneFormSet
form = OccurrenceForm
formfield_overrides = {
models.PointField: {'widget': forms.HiddenInput()},
}