Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Two foreign key fields, exactly one is set to a value, the other null in django model with MySQL database

I have a django model with two foreign key fields, one that points to product, the other points to portfolio in the code below. Exatcly one of these should be set for each Lca record. I know I can do this with MySQL triggers, but I was wondering if there was a way to make this conditional save in django

class Lca(models.Model):
    product             = models.ForeignKey(product, null=True, blank=True)
    portfolio           = models.ForeignKey(portfolio, null=True, blank=True)
    carbon_price        = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True)
    name                = models.CharField(max_length=255, blank=True)
    total_footprint     = models.IntegerField(blank=True, null=True)
    calculation_type    = models.CharField(max_length=9)
    total_cv            = models.DecimalField(max_digits=10, decimal_places=0, blank=True, null=True)
    source              = models.CharField(max_length=255, blank=True)
    date_from           = models.DateField()
    date_to             = models.DateField(blank=True, null=True)

    def __unicode__(self):
        return self.name
    # end __unicode__
# end
like image 396
MagicLAMP Avatar asked Dec 10 '13 09:12

MagicLAMP


People also ask

Can a Django model have 2 foreign keys?

First of all, anything is possible. Models can have multiple foreign keys.

Can a ForeignKey be null in Django?

ForeignKey does not allow null values.

Can you have multiple foreign keys from the same table Django?

Your intermediate model must contain one - and only one - foreign key to the source model (this would be Group in our example). If you have more than one foreign key, a validation error will be raised.

What is null true in Django models?

If a string-based field has null=True , that means it has two possible values for “no data”: NULL , and the empty string. In most cases, it's redundant to have two possible values for “no data;” the Django convention is to use the empty string, not NULL .


1 Answers

You can override the model's save method:

def save(self, *args, **kwargs):
    if self.product and self.portfolio or not self.product and not self.portfolio:
        raise ValueError('Exactly one of [Lca.product, Lca.portfolio] must be set')

    super(Lca, self).save(*args, **kwargs)

Note that this method is not applicable to bulk_create.

like image 159
jonafato Avatar answered Nov 14 '22 21:11

jonafato