Django 自定义表单字段错误地呈现值

Posted

技术标签:

【中文标题】Django 自定义表单字段错误地呈现值【英文标题】:Django custom form field incorrectly renders value 【发布时间】:2012-03-31 11:53:27 【问题描述】:

我正在尝试创建一个自定义模型字段和小部件,用于显示 google maps api v3 地图并单击选择一个点并将其存储。

数据库中的值应采用以下格式:LAT,LONG,FORMATTED_ADDRESS_BY_GOOGLE_REVERSE_GEOCODER

这是我的 fields.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个值,而是to_python()返回的LatLong对象的字符串repr。

当我调用 output = super(LatLongWidget, self).render(*args, **kwargs) 时,这会自动发生在我的小部件中

截图:

我在这里缺少什么?我应该实现更多功能吗?我做错了吗?

任何帮助将不胜感激。谢谢。

【问题讨论】:

表单上出现的字符串是 LatLong 对象的字符串表示形式,而不是 3 个逗号表示法。 问题对我来说似乎很简单。不知道你为什么被否决。 【参考方案1】:

我修改了我的小部件 render() 方法以检查传递的 value 参数的类型,并在需要时将其转换为 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)

这似乎解决了我的问题,因为传递给 render() 的 'value' 参数要么是 unicode 字符串(提交表单时),要么是显示表单时的 LatLong 对象。

【讨论】:

以上是关于Django 自定义表单字段错误地呈现值的主要内容,如果未能解决你的问题,请参考以下文章

自定义 django 表单字段渲染

以自定义表单呈现模板中的各个字段

如何使用django自定义表单保存多个到多个字段

无法在 Liferay 7.2 中呈现自定义表单字段

Django 1.4 - 在元字段 Model=User 的表单中向用户字段添加自定义错误消息

在自定义 Django 表单中验证和显示错误