Django: Вызывайте очистку формы перед очисткой модели

У меня есть модель 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 не появляется. Чтобы обойти эту проблему, я использовал форму, в которой можно ввести широту и долготу, которые затем преобразуются в Point из location.

Вот моя форма:

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

Однако функция clean модели вызывается раньше функции clean формы, что приводит к возникновению ошибки ValidationError из-за того, что координаты еще не преобразованы в Point.

Есть ли способ сначала вызвать функцию формы clean, или есть другой, более подходящий способ сделать это?

Я опубликую решение, так как оно может быть полезным для кого-то.


Проблема была в том, что я не поместил PointField, которые я определил в модели, в fields, определенные в OccurrencesInline.

Решением было добавить поле, но так как я не хотел, чтобы оно было видно, я скрыл его с помощью 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()},
    }
Вернуться на верх