【问题标题】:if...else statement inside django modeldjango 模型中的 if...else 语句
【发布时间】:2014-05-13 18:54:38
【问题描述】:

在我的 django 项目中,我需要在 model.py 中使用 if 语句。其中一个应用程序将允许用户为另一个应用程序中的文档创建元数据。所以首先我创建“元数据”类来存储它的名称、标签和字段类型,这是一个选择字段。在另一个类(MetadataValues)上,我创建了一个元数据类的 ForeignKey 和一个 if 语句,如果“元数据”类中的“fieldtype”是“text (0)”,则返回一个 charfield,或者如果“fieldtype”是“date ( 1)"。有没有办法做到这一点?我是编程新手,所以我不知道背后的所有逻辑。

代码如下:

class Metadata(models.Model)
    name = models.CharField(max_length=100, unique=True)
    label = models.CharField(max_length=100)
    METADATA_FIELD_TYPE = (
        ('0', 'Text'),
        ('1', 'Date'),
    )
    fieldtype = models.CharField(max_length=1, choices=METADATA_FIELD_TYPE, default='0')

    def __unicode__(self):
        return (self.label)


class MetadataValue(models.Model)
    metadata = models.ForeignKey(Metadata)
    if metadata.fieldtype == '0'
        value = models.CharField(max_length=100)
    else
        value = models.DateField(auto_now=False, auto_now_add=False)

    def __unicode__(self):
        return (self.metadata.label)


class Document(models.Model)
    name = models.CharField(max_length=100, unique=True)
    metadata = models.ManyToManyField(MetadataValue)

    def __unicode__(self):
        return (self.name)

【问题讨论】:

    标签: python django if-statement django-models


    【解决方案1】:

    在模型中创建表格。并且表具有严格的数据类型。一列中不能有不同的数据类型。你可以使用这个解决方案:

    class MetadataValue(models.Model)
        metadata = models.ForeignKey(Metadata)
        value_char = models.CharField(max_length=100)
        value_date = models.DateField(auto_now=False, auto_now_add=False)
    
        @property
        def value(self):
            if ...:
                return self.value_char
             return value_date
    

    【讨论】:

    • 请务必使用blank=True,如果是日期值(好吧,除了字符值之外的任何值)null=True,否则将需要所有不同类型的值。
    • 非常感谢这些对我帮助很大。
    【解决方案2】:

    您也许可以通过很多努力来强制执行此类操作,但我建议您不要这样做。您不能以直接的方式执行此类操作的原因是,每个 Django 模型(通常)都由一个或多个数据库表支持,字段对应于列。列具有单一类型,因此字段必须是 char 字段或日期,但不能同时是两者。

    您的 if 语句不起作用的原因是您需要在创建后备数据库时(即运行 manage.py syncdb)而不是创建对象时知道 metadata.fieldtype 的值。

    【讨论】:

    • 有没有其他方法可以达到同样的效果?
    • 最简单的方法是采用类似于@guettli 答案中的方法。要研究的另一件事是model inheritance,如果您使用多个子类对主 MetaData 模型进行子类化,每种类型一个子类,它可能会满足您的需求。
    【解决方案3】:

    这里是完成的代码:

    class Metadata(models.Model):
    name = models.CharField(max_length=100, unique=True, verbose_name = _('name'))  
    label = models.CharField(max_length=100, verbose_name = _('label'))
    METADATA_FIELD_TYPE = (
        ('0', 'Text (Select CharFields Values Only)'),
        ('1', 'Date (Select DateFields Values Only)'),
        ('2', 'Numeric (Select Numeric Values Only)'),
    )
    fieldtype = models.CharField(max_length=1, choices=METADATA_FIELD_TYPE, default='0', verbose_name = _('Field type'))
    char_value = models.ManyToManyField(CharValue, blank=True, verbose_name = _('CharField Value(s)'))
    date_value = models.ManyToManyField(DateValue, blank=True, verbose_name = _('DateField Value(s)'))
    numeric_value = models.ManyToManyField(NumericValue, blank=True, verbose_name = _('Numeric Value(s)'))
    def _value(self):
        if self.fieldtype == '0':
            return u'%s' % (self.char_value)
        elif self.fieldtype == '1':
            return u'%s' % (self.date_value)
        else:
            return u'%s' % (self.numeric_value)
    value = property(_value)
    class Meta:
        verbose_name = _('metadata')
        verbose_name_plural = _('metadata')
    def __unicode__(self):
        return u'%s' % (self.label)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-23
      • 1970-01-01
      • 2019-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-26
      • 2022-01-22
      相关资源
      最近更新 更多