class Product( models.Model ):
name = models.CharField(verbose_name="Name", max_length=255, null=True, blank=True)
the_products_inside_combo = models.ManyToManyField('self', verbose_name="Products Inside Combo", help_text="Only for Combo Products", blank=True)
但是,当我尝试输入重复值时出现此错误:
From_product-to_product与此From产品和To的关系 产品已经存在。
答案 0 :(得分:0)
每对(Product, Product)
必须是唯一的。这就是导致already exists
错误的原因。
在幕后,Django创建了一个中间连接表 代表多对多的关系。
你想要做的是在两个模型之间建立多对多关系(永远不要说它们是相同的)并存储其他信息 - 数量(所以你会ProductA = 2x ProductB + ...
。
为了建模这种关系,您必须创建中间模型并使用through
选项。文档解释得非常好,所以看看:
https://docs.djangoproject.com/en/dev/topics/db/models/#intermediary-manytomany
<强>更新强>
这是最小的工作示例:
class Product(models.Model):
name = models.CharField(verbose_name='Name', max_length=255, null=True, blank=True)
products = models.ManyToManyField('self', through='ProductGroup', symmetrical=False)
def __str__(self):
return self.name
class ProductGroup(models.Model):
parent = models.ForeignKey('Product', related_name='+')
child = models.ForeignKey('Product', related_name='+')
和管理员模型:
class ProductGroupInline(admin.TabularInline):
model = Product.products.through
fk_name = 'parent'
class ProductAdmin(admin.ModelAdmin):
inlines = [
ProductGroupInline,
]
admin.site.register(Product, ProductAdmin)
admin.site.register(ProductGroup)
正如您所见,递归Product
- Product
关系是使用ProductGroup
(through
参数)建模的。几个笔记:
具有中间表的多对多字段不能是对称的,因此symmetrical=False
。 Details
ProductGroup
的反向访问权限被禁用('+'
)(通常您可以重命名它们,但是,您不想直接使用ProductGroup
)。否则我们会得到Reverse accessor for 'ProductGroup.child' clashes with reverse accessor for 'ProductGroup.parent'.
。
为了在管理员中很好地展示ManyToMany,我们必须使用内联模型(ProductGroupInline
)。在文档中阅读它们。但请注意fk_name
字段。我们必须指定这个,因为ProductGroup
本身是不明确的 - 两个字段都是同一模型的外键。
谨慎使用并发费用。例如,如果您要__str__
Product
return self.products
,ProductGroup
ProductGroup
<form th:action="@{/moderator/new-user-form}" th:object="${caltest}" method="post"
enctype="multipart/form-data" class="form-validate form row">
<!-- some code -->
</form>
,<form th:action="@{/admin/new-user-form}" th:object="${caltest}" method="post"
enctype="multipart/form-data" class="form-validate form row">
<!-- some code -->
</form>
与父级相同,则无限循环。
action
并在创建对象时检查重复。