2010-04-20 73 views
3

说我有未知数量的问题。例如:如何在单个Django模型中存储任意类型的值?

  • 天空是蓝色的[Y/N]
  • 是你出生于[日期]什么日期
  • 什么是圆周率[3.14]
  • 什么是大INTEG [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返回。

如何执行这种自动转换?或者可以有人建议一个更好的方法来做到这一点?

非常感谢!

回答

5

我其实只是遇到了有关可扩展用户设置的这类问题。我的解决方案是在CharField的模型上存储该类型,并使用__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,所以我选择了值映射为bool之前强制转换为int。还有其他方法可以实现此目的,例如使用ast模块的literal_eval方法。尽管如此,整体模式仍然有效。

2

你应该没问题,只是将答案存储为字符串。如果我们谈论的是通过网络接受数据,那么无论如何你都会接收到一个字符串的输入,所以你不会因为把它作为字符串存储在数据库中而失去精确性。

一种可能的选择是为每种可能的数据类型包含一列,使它们为空。

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虽然。

+0

把它作为一个字符串是去了,恕我直言的方式,但具有类型转换回原来的值一个好的策略是非常重要的。每种类型的答案都有不同的字段,听起来很麻烦。 – 2010-04-20 22:00:43

2

我想补充一个自定义的方法,对您的问题类:

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

我认为这样做,并认识到我可以变得棘手,并避免使用上面我的帖子中的逻辑写所有额外的ifs。但绝对是正确的想法。 – 2010-04-20 21:53:30

+0

你的诀窍确实很不错。 +1 – Bolo 2010-04-20 22:18:51

相关问题