Frage

There is a model which could have multiple items linked to it, like:

from django.db import models

class MyModel(models.Model):
    name = models.CharField(max_length=100)

    def __unicode__(self):
        return self.name

class MyModelItem(models.Model):
    TYPE_CHOICES = (
        ('A', 'A NAME'),
        ('B', 'B NAME'),
        ('C', 'C NAME')
    )
    name = models.CharField(max_length=100)
    model = models.ForeignKey(MyModel, related_name='items')
    item_type = models.CharField(max_length=1, choices=TYPE_CHOICES)

    def __unicode__(self):
        return self.name

The requirement is: for each record of MyModel, don't allow more than one record of MyModelItem which has the same item_type, which means if I have:

from myproj.myapp.models import MyModel, MyModelItem

m1 = MyModel.objects.create(name='M1')

MyModelItem.objects.create(name='Item1', model=m1, item_type='A')

then I can't add another record with the same type 'A' to m1.

One solution for me is doing it like this within MyModelItem:

    ...
    def save(self, *args, **kwargs):
        if self.model.items.filter(item_type=self.item_type):
            raise IntegrityError("%s already have a item with type %s" % (self.model, self.item_type))
        super(MyModelItem, self).save(*args, **kwargs)

but this won't protect the limitation on the db level. It's possible to add such not-allowed records with SQL directly, and it can break my application. Is there an approach to implement this requirement in Django? Something like unique_together?

War es hilfreich?

Lösung

You got it, unique_together is the way to do this. It's as simple as:

class MyModelItem(models.Model): 
    ...
    name = models.CharField(max_length=100)
    model = models.ForeignKey(MyModel, related_name='items')
    item_type = models.CharField(max_length=1, choices=TYPE_CHOICES)

    class Meta:
        unique_together = ('model', 'item_type')
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top