Pointfield的纬度/经度小部件?

Art*_*urM 11 django django-forms geodjango

PointField是否有一个小部件作为单独的纬度/经度输入?就像DateTimeField的SplitDateTimeWidget一样.

Art*_*urM 8

这是我的工作自定义字段和小部件:

class LatLongWidget(forms.MultiWidget):
    """
    A Widget that splits Point input into two latitude/longitude boxes.
    """

    def __init__(self, attrs=None, date_format=None, time_format=None):
        widgets = (forms.TextInput(attrs=attrs),
                   forms.TextInput(attrs=attrs))
        super(LatLongWidget, self).__init__(widgets, attrs)

    def decompress(self, value):
        if value:
            return tuple(reversed(value.coords))
        return (None, None)

class LatLongField(forms.MultiValueField):

    widget = LatLongWidget
    srid = 4326

    default_error_messages = {
        'invalid_latitude' : _('Enter a valid latitude.'),
        'invalid_longitude' : _('Enter a valid longitude.'),
    }

    def __init__(self, *args, **kwargs):
        fields = (forms.FloatField(min_value=-90, max_value=90), 
                  forms.FloatField(min_value=-180, max_value=180))
        super(LatLongField, self).__init__(fields, *args, **kwargs)

    def compress(self, data_list):
        if data_list:
            # Raise a validation error if latitude or longitude is empty
            # (possible if LatLongField has required=False).
            if data_list[0] in validators.EMPTY_VALUES:
                raise forms.ValidationError(self.error_messages['invalid_latitude'])
            if data_list[1] in validators.EMPTY_VALUES:
                raise forms.ValidationError(self.error_messages['invalid_longitude'])
            # SRID=4326;POINT(1.12345789 1.123456789)
            srid_str = 'SRID=%d'%self.srid
            point_str = 'POINT(%f %f)'%tuple(reversed(data_list))
            return ';'.join([srid_str, point_str])
        return None
Run Code Online (Sandbox Code Playgroud)


sww*_*314 7

答案非常适合构建您自己的解决方案,但如果您想要一个看起来不错且易于使用的简单解决方案,请尝试:http : //django-map-widgets.readthedocs.io/en/latest/index.html

你可以:

  • 输入坐标
  • 直接在地图上选择
  • 从 Google 地点查找项目。

来自 Django 地图小部件的屏幕截图


rar*_*iru 5

@Ramast,以更Python的方式处理相同的问题。我已将更改合并到我的代码中,随时进行改进感觉很好。


这是我设法(最后)保留纬度和经度的单独字段而不必将其保存在数据库中的方式,因为值已经保存在PointField中。

这个想法是:

  • 如果要插入新条目,则纬度和经度字段将用于设置PointField
  • 如果我们打开现有的PointField条目,它将用于在相关FormField中提供纬度和经度值。

models.py

from django.contrib.gis.db import models as geomodels


class Entry(geomodels.Model):
    point = geomodels.PointField(
        srid=4326,
        blank=True,
        )
Run Code Online (Sandbox Code Playgroud)

管理员

from myapp.forms import EntryForm
from django.contrib import admin


class EntryAdmin(admin.ModelAdmin):
    form = EntryForm


admin.site.register(Entry, EntryAdmin)
Run Code Online (Sandbox Code Playgroud)

表格

from django import forms
from myapp.models import Entry
from django.contrib.gis.geos import Point


class MarketEntryForm(forms.ModelForm):

    latitude = forms.FloatField(
        min_value=-90,
        max_value=90,
        required=True,
    )
    longitude = forms.FloatField(
        min_value=-180,
        max_value=180,
        required=True,
    )

    class Meta(object):
        model = MarketEntry
        exclude = []
        widgets = {'point': forms.HiddenInput()}

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        coordinates = self.initial.get('point', None)
        if isinstance(coordinates, Point):
            self.initial['longitude'], self.initial['latitude'] = coordinates.tuple

    def clean(self):
        data = super().clean()
        latitude = data.get('latitude')
        longitude = data.get('longitude')
        point = data.get('point')
        if latitude and longitude and not point:
            data['point'] = Point(longitude, latitude)
        return data
Run Code Online (Sandbox Code Playgroud)