验证唯一以仅具有来自特定PropertyCategory的一个属性

时间:2013-08-02 20:20:48

标签: python django

class PropertyCategory(models.Model):

    name = models.CharField(max_length=75)

    def __unicode__(self):
        return self.name

    class Meta:
        verbose_name = _('Property Category')
        verbose_name_plural = _('Property Categories')



class Property(models.Model):

    category = models.ForeignKey(PropertyCategory)
    name = models.CharField(max_length=75)

    def __unicode__(self):
        return self.name

    class Meta:
        verbose_name_plural = 'Properties'



class Variant(models.Model):

    properties = models.ManyToManyField(Property)
    code = models.CharField(max_length=255)

    def __unicode__(self):
        product = Product.objects.get(variants__id=self.id)

        return '%s (%s)' % (product.name, ', '.join([c.name for c in self.properties.all()]))

如何在创建/更新中验证我的Variant,它只能来自同一Property一个 PropertyCategory

假设我有这个产品; Lace-trim Cheeky Panty (Pink, XS),其中括号之间的属性是来自Properties PropertyCategoryColor的{​​{1}}。我想限制Size只能拥有每个Variant中的一个,所以这样的事情不会发生;

PropertyCategory

除此之外,我想知道如果 允许有多个,可能会在Lace-trim Cheeky Panty (Pink, XS, Blue, M)上设置一个特殊值。假设洗涤说明 可以 多次出现。我怎么能发现这种差异?

PropertyCategory

..但是,如果用户以后决定将class PropertyCategory(models.Model): name = models.CharField(max_length=75) multi_instance = models.BooleanField() # This determines if the Category's Properties can be applied more than once on a Variant ... multi_instance设置为True等,此功能可能会产生更多问题,因为它可能会破坏关系。

也许我可以使用False延长正常PropertyCategory

1 个答案:

答案 0 :(得分:1)

不幸的是,这是一个常见问题。即使properties看起来像是Variant的一部分,ManyToManyField声明实际上也会导致创建一个引用VariantsProperties的全新表通过他们的主键。因此,当创建Variant时,严格来说, no Properties与之关联,因为只有在数据库中存在Variant时才会发生这种情况。这就是为什么尝试通过覆盖Model.save()方法(一种常见的第一种方法)来进行验证的原因是无效的。

同样,您可以通过覆盖Model.clean()方法提供custom validation,但在调用此方法时(例如,通过ModelForm.is_valid()),对象及其引用尚未被提及添加到数据库中。

如果您正在使用Django的表单(包括管理站点),请查看ModelForm validation。基本上,您将覆盖ModelForm的clean()方法并验证表单而不是Model本身。

关于你的第二个问题,你添加BooleanField的想法听起来不错。如果您担心用户不当更改该值,则可以使用管理网站中的权限控制他们对PropertyCategories的访问权限(或通过验证限制更改)。你是正确的,将值从True更改为False会产生问题,但这是一个概念问题,无论您选择何种方法实施,都是如此。