Поле пользовательской формы Django неправильно отображает значение - PullRequest
3 голосов
/ 15 марта 2012

Я пытаюсь создать настраиваемое поле модели и виджет для отображения карты Google Maps api v3, щелчка мышью, выбора точки и ее сохранения.

Значение в базе данных должно быть в следующем формате: LAT, LONG, FORMATTED_ADDRESS_BY_GOOGLE_REVERSE_GEOCODER

Вот мои поля.py:

from django.db import models

class LatLong(object):

    def __init__(self, *args, **kwargs):
        self.lat = kwargs.get('lat',0)
        self.long = kwargs.get('long',0)
        self.addr = kwargs.get('addr','')

class CoordField(models.Field):

    description = 'Coordinates field'
    __metaclass__ = models.SubfieldBase

    def __unicode__(self):
        return 'LatLong obj'

    def __init__(self, *args, **kwargs):
        kwargs['max_length'] = 255 
        super(CoordField, self).__init__(*args, **kwargs)

    def db_type(self, connection):
        return 'varchar(%s)' % self.max_length

    def get_prep_value(self, value):
        return '%s,%s,%s' % (value.lat, value.long, value.addr)

    def to_python(self, value):
        if isinstance(value, LatLong):
            return value

        try:
            x = value.split(',')
        except:
            return LatLong(lat=0,long=0,addr='')

        return LatLong(lat=x[0], long=x[1], addr=','.join(x[2:]))

И мои widgets.py:

from django.forms import Widget, TextInput

from django.template.loader import render_to_string

from django.utils.safestring import mark_safe

from settings import GMAPS_API_KEY


class LatLongWidget(TextInput):

    class Media:
        css = { 
            'all':('testing.css',)
        }   
        js = ( 
            'resource/js/coord.js',
        )   

    def __init__(self, attrs=None):
        default_attrs = {}

        if attrs:
            default_attrs.update(attrs)

        super(LatLongWidget, self).__init__(default_attrs)

    def render(self, *args, **kwargs):
        output = super(LatLongWidget, self).render(*args, **kwargs)

        output += render_to_string('maps/coord.html',
                                    {'GMAPS_API_KEY':GMAPS_API_KEY,
                                     'latlong': args[1]})

        return mark_safe(output)

Насколько я понимаю, определение to_python () из поля всегда должно возвращать объект python, а get_prep_value () должно делать прямо противоположное.

Как вы можете видеть на скриншоте ниже, вывод поля в форме - это не 3 значения, разделенные запятой, а строковое представление объекта LatLong, возвращаемое to_python ().

Это автоматически происходит в моем виджете, когда я звоню output = super(LatLongWidget, self).render(*args, **kwargs)

Снимок экрана: http://imgur.com/qnuSu

Что мне здесь не хватает? Должен ли я реализовать больше функций? Я сделал это совершенно неправильно?

Буду признателен за любую помощь. Спасибо.

1 Ответ

3 голосов
/ 15 марта 2012

Я изменил свой метод render () для виджета, чтобы проверить тип передаваемого параметра-значения и преобразовать его в объект LatLong, если необходимо, так:

def render(self, name, value, attrs=None):
    if not isinstance(value, LatLong):
        value = value.split(',')
        value = LatLong(lat=value[0], long=value[1], addr=value[2:])

    output = super(LatLongWidget, self).render(name, '%s,%s,%s' % (value.lat, value.long, value.addr), attrs)

    output += render_to_string('maps/coord.html',
                                {'GMAPS_API_KEY':GMAPS_API_KEY,
                                 'latlong': value,
                                 'id':attrs['id'],})

    return mark_safe(output)

Это, похоже, исправило мою проблемупараметр 'value', передаваемый в render (), является либо строкой Unicode (при отправке формы), либо объектом LatLong при отображении формы.

...