postgresql ManyToManyField未正确保存

zz2j4svz  于 2023-06-22  发布在  PostgreSQL
关注(0)|答案(1)|浏览(121)

我有一个item_option,这是一个ManyToManyFiled,链接到一个ItemOption模型。
在Django面板中,我可以插入ItemOptions,它们被正确地保存在数据库中,但是product.item_option.all()返回一个空数组。
我发现ItemOption正在插入,但ManyToManyTable database_product_item_option中没有插入任何内容。
手动将索引添加到这个表中解决了这个问题,我可以使用product.item_option.all()成功地检索ItemOptions
我如何让Django自动完成这些?我觉得我已经接近解决方案了,但我还没有找到我的代码有什么问题或者缺少了什么。
下面是我的代码:
产品展示

class Product(models.Model):
    id = models.AutoField(primary_key=True)
    ...
    item_option = models.ManyToManyField('ItemOption', blank=True, related_name='item_option')

ItemOption

class ItemOption(models.Model):
    product = models.ForeignKey(Product, on_delete=models.CASCADE)

    name = models.CharField(max_length=100, blank=True, null=True)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    default = models.BooleanField(default=False)

形式

class ItemOptionForm(forms.ModelForm):
    class Meta:
        model = ItemOption
        fields = ['name', 'price', 'default']

class ItemOptionInline(admin.TabularInline):
    model = ItemOption
    form = ItemOptionForm
    extra = 1
    can_delete = True

class ProductAdmin(admin.ModelAdmin):
    list_display = ('title', 'price', 'product_type')
    list_filter = ('product_type', 'brand')
    exclude = ('item_option',)
    inlines = [ItemOptionInline]

admin.site.register(Product, ProductAdmin)
nmpmafwu

nmpmafwu1#

你有两个链接,一个ForeignKey和一个ManyToManyField,这可能没有多大意义。虽然从根本上讲不是不可能的,但通常从一个模型到另一个模型都有ForeignKey,或者在两者之间有ManyToManyField。这里的ModelAdmin选择了product外键,因为这是唯一的东西,InlineModelAdmin可以使用“开箱即用”。
如果您想使用ManyToManyField,这并不简单。但如果定义了ManyToManyField,则创建了一个(隐藏)模型。事实上,一个有两个ForeignKey的:在这种情况下,一个指向Product,一个指向ItemOption。因此,我们可以按照文档的 * 使用多对多模型 * 部分中指定的方式使用该模型:

class ItemOptionThroughInline(admin.TabularInline):
    model = Product.item_option.through
    extra = 1
    can_delete = True

class ProductAdmin(admin.ModelAdmin):
    list_display = ('title', 'price', 'product_type')
    list_filter = ('product_type', 'brand')
    exclude = ('item_option',)
    inlines = [ItemOptionThroughInline]

然而,这将仅使得指向已经存在的ItemOption变得方便。如果有ItemOption表单也会很奇怪:这意味着,如果您通过一个产品的编辑页面更改了链接在两个Product上的ItemOption,则该更改因此也反映在另一个产品的编辑页面中。因此,您可能只是想要ItemOption型号中的ForeignKey,并针对(单个)Product进行选择。

相关问题