Django:模型的单个实例中的所有IntegerField必须彼此唯一

时间:2015-09-01 15:27:55

标签: django django-models

我正在使用django-solo来创建一个只能有一个类型实例的模型。 https://github.com/lazybird/django-solo

我有这样的模型

class ProductPropertiesPriority(SingletonModel):
    product_type = models.PositiveIntegerField(validators=[
            MaxValueValidator(6),
            MinValueValidator(1)
        ],
        default=1)
    style = models.PositiveIntegerField(validators=[
            MaxValueValidator(6),
            MinValueValidator(1)
        ],
        default=2)
    color = models.PositiveIntegerField(validators=[
            MaxValueValidator(6),
            MinValueValidator(1)
        ],
        default=3)
    series = models.PositiveIntegerField(validators=[
            MaxValueValidator(6),
            MinValueValidator(1)
        ],
        default=4)
    size = models.PositiveIntegerField(validators=[
            MaxValueValidator(6),
            MinValueValidator(1)
        ],
        default=5)
    brand = models.PositiveIntegerField(validators=[
            MaxValueValidator(6),
            MinValueValidator(1)
        ],
    default=6)

这里我想为每个字段设置优先级。我希望单个实例中的所有IntegerField彼此都是唯一的。一个字段的值不应与任何其他字段匹配。

我该如何解决这个问题。请帮忙。

2 个答案:

答案 0 :(得分:1)

您需要在模型的Meta类中定义unique_together

  

一起使用的字段名称集必须是唯一的。

class ProductPropertiesPriority(SingletonModel):
    ...

    class Meta:
        # set of fields that must be unique together
        unique_together = (('product_type', 'style', 'color', `series`, `size`, 'brand'),)

Django将确保unique_together选项中定义的元组元组在一起考虑时必须是唯一的。它将在Django管理员中使用,并在数据库级别强制执行。

修改

上述方法将确保模型的不同实例之间的唯一性。要确保特定模型实例的不同字段之间的唯一性,您需要执行模型验证。

您可以通过覆盖模型中的.clean()方法并在那里编写验证来完成此操作。

在这里,在clean()方法中,我们将获取字段的值并比较它们是否是不同的。如果它们不相同,那么我们将提出验证错误。另外,我们覆盖模型中的.save()并调用.full_clean()方法,因为此方法也会调用.clean()和其他一些方法。

from django.core.exceptions import ValidationError

class ProductPropertiesPriority(SingletonModel):
    ...

    def clean(self, *args, **kwargs):
        """
        Write your custom validation to check for unique values here
        """
        my_unique_fields = ['product_type', 'style', 'color', 'series', 'size', 'brand']
        values = []
        for field in my_unique_fields:
            values.append(getattr(self, field))
        if len(values) != len(my_unique_fields):
            raise ValidationError(_('All the values must be distinct.'))
        super(ProductPropertiesPriority, self).clean(*args, **kwargs)

    def save(self, *args, **kwargs):
        self.full_clean() # call the full_clean() method
        super(ProductPropertiesPriority, self).save(*args, **kwargs)

注意: Django默认情况下在调用full_clean()时不会调用save()方法(有关详细信息,请查看此SO link)。你必须自己调用这个方法。

答案 1 :(得分:0)

一种方法是覆盖模型中的clean(),检查其中的字段,如果两个或多个相同,则引发验证错误。

我不能说这是否是最佳方式。