如何在单个Django模型中存储任意类型的值?

时间:2010-04-20 21:26:12

标签: python django django-models

说我的问题数量未知。例如:

  • 天蓝色[y / n]
  • 您[出生日期]的出生日期
  • 什么是pi [3.14]
  • 什么是大型整合[100]

现在,这些问题中的每一个都提出了一个不同但非常类型的答案(布尔值,日期,浮点数,整数)。本土django可以在模型中愉快地处理这些问题。

class SkyModel(models.Model):
    question = models.CharField("Is the sky blue")
    answer = models.BooleanField(default=False)

class BirthModel(models.Model):
    question = models.CharField("What date were your born on")
    answer = models.DateTimeField(default=today)

class PiModel(models.Model)
    question = models.CharField("What is pi")
    answer = models.FloatField()

但这有一个明显的问题,即每个问题都有一个特定的模型 - 所以如果我们以后需要添加一个问题,我必须更改数据库。呸。所以现在我想得到一种想法 - 如何通过答案类型转换自动地设置模型?

ANSWER_TYPES = (
    ('boolean', 'boolean'),
    ('date', 'date'),
    ('float', 'float'),
    ('int', 'int'),
    ('char', 'char'),
)

class Questions(models.model):
    question = models.CharField(()
    answer = models.CharField()
    answer_type = models.CharField(choices = ANSWER_TYPES)
    default = models.CharField()

所以理论上这会做到以下几点:

  • 当我建立自己的观点时,我会看到答案的类型,并确保我 只有这个价值。
  • 但是当我想将该答案拉回来时,它将以answer_type指定的格式返回数据。例3.14以浮动形式返回,而不是str。

我如何进行这种自动转换?或者有人可以提出更好的方法吗?

非常感谢!!

3 个答案:

答案 0 :(得分:5)

我实际上只是遇到了有关可扩展用户设置的这类问题。我的解决方案是将模型中的类型存储在CharField中,并使用getter通过智能使用__builtin__getattr来进行类型转换。这是我的代码(适应您的需求):

VALUE_TYPE_CHOICES = (
    ("unicode", "Unicode String"),
    ("int", "Integer"),
    ("bool", "Boolean"),
)

class Setting(models.Model):
    name = models.CharField(max_length=100)
    description = models.TextField(blank=True)
    type = models.CharField(max_length=50, choices=VALUE_TYPE_CHOICES)
    default_value = models.CharField(max_length=127)

def get_setting(user, setting_id):
    profile_setting = #get the user's specific setting value here, not relevant
    type = getattr(__builtin__, profile_setting.setting.type)
    if type is bool:
        return type(int(profile_setting.value))
    else:
        return type(profile_setting.value)

其中有一个问题:bool('0')实际上返回True,所以我选择在转换为int之前将其转换为bool。还有其他方法可以实现此目的,例如使用ast模块的literal_eval方法。总的来说,这种模式很有效。

答案 1 :(得分:2)

你应该把答案存储为字符串。如果我们谈论通过Web接受数据,那么无论如何你都会以字符串形式接收输入,所以你不会因为将它作为字符串存储在数据库中而失去精度。

一种可能的替代方法是为每种可能的数据类型包含一列,允许它们为空。

class Questions(models.model):
    question = models.CharField(()
    answer = models.CharField()
    answer_type = models.CharField(choices = ANSWER_TYPES)
    int_answer = models.IntegerField(null=True)
    bool_answer = models.NullBooleanField(null=True)
    ... etc. 

如果是我,我会坚持使用单CharField

答案 2 :(得分:2)

我会在您的Questions类中添加一个自定义方法:

def get_converted_answer(self):
  if self.answer_type == 'int':
    return int(self.answer)
  if self.answer_type == 'bool':
    # ...