0
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 on Creation/Update 它只能有一个 Property来自同一个PropertyCategory.

假设我有这个产品;Lace-trim Cheeky Panty (Pink, XS), 其中括号之间的属性是PropertiesfromPropertyCategory ColorSize. 我想限制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_instancefrom TruetoFalse等,它可能会破坏关系。

也许我可以PropertyCategoryMultiPropertyCategory?

4

1 回答 1

1

不幸的是,这是一个常见问题。尽管properties看起来它是 a 的一部分,但VariantManyToManyField声明实际上导致创建一个全新的表,该表同时引用VariantsProperties通过它们的主键。因此Variant,严格来说,当创建a 时,它没有 Properties关联,因为只有Variant在数据库中存在时才会发生这种情况。这就是为什么试图通过覆盖该Model.save()方法(一种常见的第一种方法)来进行验证是行不通的。

类似地,您可以通过覆盖该方法来提供自定义验证Model.clean(),但在调用此方法时(ModelForm.is_valid()例如通过),对象及其引用尚未添加到数据库中。

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

至于您的第二个问题,您添加 a 的想法BooleanField对我来说听起来不错。如果您担心用户不当更改该值,那么您可以控制他们PropertyCategories在管理站点中使用权限的访问权限(或通过验证限制更改)。您是对的,将值从Trueto更改False会出现问题,但这是一个概念性问题,无论您选择哪种特定实现方法都是如此。

于 2013-08-02T23:02:04.410 回答