2013-06-10 6 views

उत्तर

6

यहाँ मेरे कार्य कस्टम फ़ील्ड और विजेट है:

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 
+1

जब मैं इस – fangsterr

+0

का उपयोग @fangsterr आप उपयोग कर सकते हैं '' '' '' FloatField''' या DecimalField''' अपने निर्देशांक और ओवरराइड स्टोर करने के लिए मैं एक 'अमान्य ज्यामिति मान' त्रुटि मिलती है जैसा कि सचित्र [यहां] (http://stackoverflow.com/a/22309195/2996101) के रूप में '' 'PointField'' को अपडेट करने के लिए सहेजने की विधि – raratiru

0

इसके लिए एक कस्टम विजेट बनाएं, आप SelectDateWidgethere से प्रेरित हो सकते हैं।

3

@Ramast, एक और अधिक pythonic तरह से एक ही मुद्दे दृष्टिकोण। मैंने अपने कोड में बदलावों को शामिल किया है, यह हमेशा सुधारने के लिए बहुत अच्छा लगता है।


यह मैं कैसे last- कम से कामयाब उन्हें डेटाबेस में बचाने के लिए के बाद से मूल्यों को पहले से ही PointField में सहेजे जाते हैं बिना lattitude और देशांतर के लिए अलग-अलग फ़ील्ड रखने के लिए है।

विचार है:

  • हम एक नई प्रविष्टि डालने रहे हैं, तो अक्षांश और देशांतर क्षेत्रों PointField
  • अगर हम एक मौजूदा PointField प्रविष्टि खोलते हैं, तो यह करने के लिए इस्तेमाल किया जाएगा स्थापित करने के लिए उपयोग किया जाएगा प्रासंगिक फॉर्मफिल्ड्स में अक्षांश और देशांतर मान प्रदान करें।

models.py

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


class Entry(geomodels.Model): 
    point = geomodels.PointField(
     srid=4326, 
     blank=True, 
     ) 

admin.py

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


class EntryAdmin(admin.ModelAdmin): 
    form = EntryForm 


admin.site.register(Entry, EntryAdmin) 

forms.py

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['latitude'], self.initial['longitude'] = 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 
3

यह @ rara_tiru के समाधान के लेकिन कुछ सुधार के साथ आधारित है

class GisForm(forms.ModelForm): 
    """ 
    This form can be used by any model that has "coordinates" field. 
    It will show a better looking map than the default one 
    """ 
    lat = forms.FloatField(required=False) 
    lng = forms.FloatField(required=False) 
    coordinates = PointField(widget=CustomPointWidget(), required=False, srid=4326) 

    def __init__(self, *args, **kwargs): 
     super(GisForm, self).__init__(*args, **kwargs) 
     coordinates = self.initial.get("coordinates", None) 
     if isinstance(coordinates, Point): 
      self.initial["lng"], self.initial["lat"] = coordinates.tuple 

    def clean(self): 
     data = super(GisForm, self).clean() 
     if "lat" in self.changed_data or "lng" in self.changed_data: 
      lat, lng = data.pop("lat", None), data.pop("lng", None) 
      data["coordinates"] = Point(lng, lat, srid=4326) 

     if not (data.get("coordinates") or data.get("lat")): 
      raise forms.ValidationError({"coordinates": "Coordinates is required"}) 
     return data 

यह मूल रूप से उपयोगकर्ताओं को मानचित्र पर स्थान सेट करने या मैन्युअल रूप से lat/lng मानों को रखने की अनुमति देगा। एक बार सहेजे गए नक्शे को निर्दिष्ट किया अक्षांश/एलएनजी मूल्य को प्रतिबिंबित करेगा

1

जवाब अपने स्वयं के समाधान के निर्माण के लिए महान हैं, लेकिन अगर आप एक सरल उपाय है कि अच्छा लग रहा है और प्रयोग करने में आसान है करना चाहते हैं, की कोशिश: http://django-map-widgets.readthedocs.io/en/latest/index.html

आप कर सकते हैं:

  • निर्देशांक दर्ज
  • नक्शा
  • गूगल स्थानों से आइटम को देखने पर सीधे का चयन करें।

Screen Shot from Django Map Widgets

संबंधित मुद्दे