2017-01-07 13 views
0

У меня есть одна форма и одна форма в моем проекте django. Форма имеет один вход с геометрией Точки. Поэтому у меня есть вход там, который выглядит примерно так:GeoDjango сохранение геометрии точки из формы

39.237103, 25,667217

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

position = gismodels.PointField(null=True, srid=4326) 

Я использую этот код для проверки и сохранения формы, formset и точки геометрии

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 для позиции имеет плохой формат, чтобы проверка checklist_form поднять эту ошибку прежде, чем я могу разделить координаты:

Строка или юникода вход непризнанные в WKT EWKT и HEXEWKB.

Я читал, что могу скопировать данные POST и изменить их, но я также прочитал, что это плохая практика. Я думаю об использовании javascript для изменения координат для соответствующего формата, но GeoDjango, безусловно, имеет лучшую функциональность для сохранения геометрии точки.

ответ

1

Вот простое поле для ввода или редактирования Point с с помощью Джанго:

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 
1

Хорошо, я понял. Мне пришлось добавить функцию clean_position(self), которая редактирует данные формы django перед проверкой (функция .is_valid()). Затем я легко изменяю формат поля ввода.

Вот как выглядит мой clean_position(self) функция в настоящее время:

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

Имейте в виду, что это решение не подтверждает ввод и произойдет сбой, если вход в неправильном формате. Это всегда непригодно для редактирования существующих точек. – Udi