【问题标题】:Preprocess value from DB before showing in Admin在 Admin 中显示之前预处理来自 DB 的值
【发布时间】:2012-03-11 07:03:13
【问题描述】:

我的问题很简单,但我无法解决我的问题:每次在管理员中显示字段时,我都需要处理一个字段,因为它必须以不同的方式保存在数据库中。

例如,我需要用户在管理员中输入百分比(比如 50、70 或 100),但这些值将在数据库中保存为 0.5、0.7 或 1。之后,当用户想要编辑或者只是查看这些值,即使它们在数据库中保存为浮点数,也不必对它们进行预处理以再次将它们显示为百分比(整数)。

我的想法是这样的:

def valid_percentage(value):
    if not 0 <= value <= 1:
        raise ValidationError(u'Must be a value between 0 and 100')

class PercentageField(models.IntegerField):    
    def __init__(self, *args, **kwargs):
        kwargs['validators'] = kwargs.get('validators', []) + [valid_percentage]
        super(PercentageField, self).__init__(*args, **kwargs)

    def to_python(self, value):
        return None if value is None else int(100 * value)

    def get_prep_value(self, value):
        return None if value is None else value/100.0

会做的。但这是保存和显示数据都错了。

【问题讨论】:

  • 你可能不应该继承IntegerField,因为你不会在数据库中存储整数。请改用DecimalFieldFloatField

标签: database django django-admin


【解决方案1】:

尝试get_db_prep_value,然后查看数据库以查看它在哪一步失败。

【讨论】:

    【解决方案2】:

    我走了很远,得到了一个用于保存的代码版本,另一个用于显示的代码版本。所以这很有趣,但不是很有用。

    实现你想要的正确的是:

    1. 在模型类定义中使用简单的 DecimalField 或 FloatField

    2. 为您的模型创建ModelForm

    3. 在您的 ModelForm 中定义 clean_yourpercentagefield() 以将输入值除以 100

    4. 制作并使用自定义小部件类在渲染前将值乘以 100

    django custom fields and modelform documentation所述:

    您必须确保用于表示您的自定义字段的表单字段执行任何必要的输入验证和数据清理,以便将用户提供的表单输入转换为与 to_python() 兼容的模型字段值。这可能需要编写自定义表单字段,和/或在您的字段上实现 formfield() 方法以返回其 to_python() 返回正确数据类型的表单字段类。

    确实,您还可以采取以下步骤:

    1. 创建一个 PercentageField 类覆盖 formfield()

    2. 创建 PercentageFormField 应由 PercentageField.formfield() 调用

    3. 创建 PercentageWidget PercentageFormField 将默认使用的

    如果您打算按照您建议的方式进行操作,您将遇到的错误是 to_python() 被一遍又一遍地调用多次,基本上使用以下代码:

    def to_python(self, value):
        print 'to python', value
        value = None if value is None else int(100 * value)consider this section of the documentation
        print 'converted to python', value
        return value
    

    从模型表单中保存模型将输出如下内容:

    to python 32.0
    converted to python 3200
    clean 3200
    to python 3200
    converted to python 320000
    

    如果您坚持要以错误的方式进行操作,您将必须使用SubFieldMetaclass

    结论:KISSFTW

    感谢 SmileyChris 提供了这个答案,这可能并不完美,但我认为不分享我的发现太糟糕了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-01
      • 1970-01-01
      • 2013-12-19
      • 1970-01-01
      • 2014-10-28
      • 2020-01-10
      • 1970-01-01
      • 2011-12-23
      相关资源
      最近更新 更多