GeoDjango从表单保存点几何图形

GeoDjango从表单保存点几何图形,django,forms,coordinates,point,geodjango,Django,Forms,Coordinates,Point,Geodjango,我在django项目中有一个表单和一个表单集。该表单有一个带有点几何图形的输入。我在这里输入了如下内容: 39.237103、25.667217 当用户发送表单时,我希望拆分此输入并将其另存为点几何图形,在模型中,点如下所示: position = gismodels.PointField(null=True, srid=4326) 我使用此代码验证和保存表单、表单集和点几何图形 if request.method == "POST": checklist_form = Checkli

我在django项目中有一个表单和一个表单集。该表单有一个带有点几何图形的输入。我在这里输入了如下内容:

39.237103、25.667217

当用户发送表单时,我希望拆分此输入并将其另存为点几何图形,在模型中,点如下所示:

position = gismodels.PointField(null=True, srid=4326)
我使用此代码验证和保存表单、表单集和点几何图形

if request.method == "POST":
    checklist_form = ChecklistForm(request.POST)
    observation_formset = ObservationFormSet(request.POST)

    #error
    if checklist_form.is_valid() and observation_formset.is_valid():
        checklist = checklist_form.save(commit=False)
        latitude, longitude = request.POST.get('position', '').split(', ', 1)
        checklist.position = Point(longitude, latitude)
        checklist.save()
        for observation_form in observation_formset:
            observation = observation_form.save(commit=False)
            observation.checklist_id = checklist
            observation.save()
但问题是位置的POST数据格式不正确,因此在我分割坐标之前,检查表的验证会引发此错误:

无法识别为WKT EWKT和HEXEWKB的字符串或unicode输入


我读到我可以复制POST数据并更改它们,但我也读到这是一种糟糕的做法。我考虑的是使用javascript更改坐标以获得适当的格式,但GeoDjango在保存点几何图形方面肯定有更好的功能。

好的,我知道了。我必须添加函数
clean_position(self)
,它在验证之前编辑django表单数据(函数
。is_valid()
)。然后我很容易改变输入字段的格式

这就是我的
清洁位置(自我)
功能现在的样子:

def clean_position(self):
    coordinates = self.cleaned_data['position']
    latitude, longitude = coordinates.split(', ', 1)
    return GEOSGeometry('POINT('+longitude+' '+latitude+')')

下面是一个使用django输入或编辑点的简单字段:

import re
from django.contrib.gis import forms
from django.contrib.gis.geos import Point
from django.core.exceptions import ValidationError
from django.utils.encoding import force_text
from django.utils.translation import ugettext_lazy as _


class SimplePointField(forms.Field):
    default_error_messages = {
        'invalid': _('Enter latitude,longitude'),
    }
    re_point = re.compile(r'^\s*(-?\d+(?:\.\d+)?),\s*(-?\d+(?:\.\d+)?)\s*$')

    def prepare_value(self, value):
        if isinstance(value, Point):
            return "{},{}".format(*value.coords)
        return value

    def to_python(self, value):
        """
        Validates input. Returns a Point instance or None for empty values.
        """
        value = super(SimplePointField, self).to_python(value)
        if value in self.empty_values:
            return None
        try:
            m = self.re_point.match(force_text(value))
            if not m:
                raise ValueError()
            value = Point(float(m.group(1)), float(m.group(2)))
        except (ValueError, TypeError):
            raise ValidationError(self.error_messages['invalid'],
                                  code='invalid')

        return value

# usage exmaple:
class MyForm(forms.Form):
    point = SimplePointField()  # this one is required
    other_point = SimplePointField(required=False)  # can stay blank

请记住,此解决方案不会验证您的输入,如果输入格式不正确,则将失败。它始终无法用于编辑现有点。当数据不准确时,可能会崩溃(请参阅GEOSException)