Django Unique Together (с внешними ключами) - PullRequest
56 голосов
/ 14 декабря 2010

У меня есть ситуация, когда я хочу использовать мета-опции unique_together для применения определенного правила, вот модель-посредник:

class UserProfileExtension(models.Model):
    extension = models.ForeignKey(Extension, unique=False)
    userprofile = models.ForeignKey(UserProfile, unique=False)
    user = models.ForeignKey(User, unique=False)  

    class Meta:
        unique_together = (("userprofile", "extension"),
                           ("user", "extension"),
                           # How can I enforce UserProfile's Client 
                           # and Extension to be unique? This obviously
                           # doesn't work, but is this idea possible without
                           # creating another FK in my intermediary model 
                           ("userprofile__client", "extension"))

и вот UserProfile:

class UserProfile(models.Model):
    user = models.ForeignKey(User, unique=True)
    client = models.ForeignKey(Client)

Спасибо.

Ответы [ 4 ]

63 голосов
/ 14 декабря 2010

Вы не можете.

Предложение unique_together напрямую переводится в уникальный индекс SQL.И вы можете установить их только для столбцов одной таблицы, а не для комбинации нескольких таблиц.

Вы можете сами добавить проверку для нее, просто переписав метод validate_unique и добавив эту проверку в него.

Документы: http://docs.djangoproject.com/en/dev/ref/models/instances/#django.db.models.Model.validate_unique

10 голосов
/ 01 августа 2012

Моим решением было использовать get_or_create Джанго. При использовании get_or_create бесполезное получение произойдет, если строка уже существует в базе данных, и строка будет создана, если она не существует.

Пример:

 
extension = Extension.objects.get(pk=someExtensionPK)<br />
userProfile = UserProfile.objects.get(pk=someUserProfilePK)<br />
UserProfileExtension.objects.get_or_create(extension=extension, userprofile=userProfile)
3 голосов
/ 18 марта 2019

Мои 2 цента, дополняют принятый ответ от @ Wolph

Вы можете сами добавить для него проверку, просто переписав метод validate_unique и добавив в него эту проверку.

Это рабочий пример кода, который кто-то может найти полезным.

from django.core.exceptions import ValidationError


class MyModel(models.Model):

    fk = models.ForeignKey(AnotherModel, on_delete=models.CASCADE)

    my_field = models.CharField(...)  # whatever

    def validate_unique(self, *args, **kwargs):
        super(MyModel, self).validate_unique(*args, **kwargs)

        if self.__class__.objects.\
                filter(fk=self.fk, my_field=self.my_field).\
                exists():
            raise ValidationError(
                message='MyModel with this (fk, my_field) already exists.',
                code='unique_together',
            )
1 голос
/ 22 мая 2019

В версиях django 2.2+ предлагается использовать ограничение и индекс в качестве мета-опции класса модели:

https://docs.djangoproject.com/en/2.2/ref/models/options/#django.db.models.Options.unique_together

https://docs.djangoproject.com/en/2.2/ref/models/options/#django.db.models.Options.constraints

...