Question

I have a situation on my django project where i need to use an if statement inside a model.py. One of the apps will allow users to create metadata for a document in the other app. So first i create "Metadata" class that stores its name, label and fieldtype, which is a choice field. On another class (MetadataValues) i create a ForeignKey to Metadata class and an if statement that return a charfield if "fieldtype" inside the "Metadata" class is "text (0)" or return a datefield if "fieldtype" is "date (1)". Is there a way to do this?, im new into programming so i don't know all the logic behind.

Here is the code:

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)
Was it helpful?

Solution

In the model you create tables. And tables have strict data types. You can't have different data types in one column. You could use this solution:

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

OTHER TIPS

You might be able to force something like this to work with a lot of effort, but I would advise against it. The reason that you can't do something like this in a straightforward way is that every Django model is (normally) backed by one or more database tables, with fields corresponding to columns. Columns have a single type, so a field must be either a char field or a date, but not both.

The reason that your if statement won't work is that you would need to know the value of metadata.fieldtype when the backing database is created (i.e. when you run manage.py syncdb), not when the object is created.

Here is the code Finished:

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)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top