在Admin中显示之前来自DB的预处理值

时间:2012-02-20 22:47:35

标签: database django django-admin

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

例如,我需要用户在管理员中输入百分比(例如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

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

2 个答案:

答案 0 :(得分:2)

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

正确实现你想要的是:

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

  2. 为您的模型创建ModelForm

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

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

  5. django custom fields and modelform documentation所述:

      

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

    的确,您也可以采取以下措施:

    1. 创建PercentageField类覆盖formfield()

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

    3. 创建PercentageWidget ,默认情况下PercentageFormField将使用

    4. 如果您打算以您建议的方式执行此错误,那么您将遇到的错误是,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

      结论:KISS FTW

      向SmileyChris致信,这个答案可能并不完美,但我认为不分享我发现的内容真是太糟糕了。

答案 1 :(得分:0)

尝试get_db_prep_value然后查看数据库以查看它失败的步骤。