代码之家  ›  专栏  ›  技术社区  ›  ufk

Django管理中的ManyToMany作为Muti选择复选框

  •  0
  • ufk  · 技术社区  · 3 年前

    我使用的是python 3.9和django 4.1。

    我有公寓清单和商品清单,每个公寓可以有零个或多个商品。

    模式是这样创建的:

    class Commodities(models.Model):
        name_en = models.CharField(verbose_name=_('English Name'), unique=True, blank=True, null=True, max_length=200)
        name_he = models.CharField(verbose_name=_('Hebrew Name'), unique=True, blank=True, null=True, max_length=200)
        name_fr = models.CharField(verbose_name=_('French Name'), unique=True, blank=True, null=True, max_length=200)
    
        class Meta:
            constraints = [
                models.CheckConstraint(
                    check=Q(name_en__isnull=False) | Q(name_he__isnull=False) | Q(name_fr__isnull=False),
                    name='not_all_null_commodities'
                )
            ]
    
        def __str__(self):
            return getattr(self, 'name_' + get_2l_lang())
    
    
    class Apartment(models.Model):
        address = models.ForeignKey(Address, verbose_name=_('Apartment Address'), on_delete=models.CASCADE)
        floor = models.IntegerField(verbose_name=_('Floor'), null=True, blank=True)
        apartment = models.CharField(verbose_name=_('Apartment'), null=True, blank=True, max_length=10)
    
        def __str__(self):
            return self.address.__str__() + \
                   (' ' + _('Entrance') + ' ' + self.address.entrance if self.address.entrance else '') + \
                   (' ' + _('Floor') + ' ' + str(self.floor) if self.floor else '') + \
                   (' ' + _('Apartment') + ' ' + self.apartment if self.apartment else '')
    
    
    class ApartmentCommodities(models.Model):
        apartment = models.ForeignKey(Apartment, on_delete=models.CASCADE, verbose_name=_('Apartment'))
        commodity = models.ForeignKey(Commodities, on_delete=models.CASCADE)
    
        def __str__(self):
            return self.apartment.__str__() + ' - ' + getattr(self.commodity, 'name_' + get_2l_lang())
    

    我希望在管理页面中,当我添加或修改公寓时,将商品视为多复选框,而不是逐行选择添加和删除每个商品。

    我在谷歌上搜索了很多。。我在上读到了filter_horizontal https://docs.djangoproject.com/en/4.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin.filter_horizontal

    我试着试一试

    所以我创建了一个 forms.py 使用此代码:

    class CommoditiesModelForm(forms.ModelForm):
        class Meta:
            model = Commodities
            fields = '__all__'
    
        def __init__(self, *args, **kwargs):
            forms.ModelForm.__init__(self, *args, **kwargs)
            self.fields['commodities'].queryset = Commodities
    

    然后我创造了 admin.ModelAdmin 对于公寓

    class ApartmentAdmin(admin.ModelAdmin):
        form = CommoditiesModelForm
        list_display = ('get_country', 'get_city', 'get_street', 'get_number', 'get_entrance', 'apartment', 'floor')
        #inlines = [ApartmentCommoditiesInline]
        filter_horizontal = ('commodities',)
    

    但这会返回错误:

    <class 'goods.admin.ApartmentAdmin'>: (admin.E019) The value of 'filter_horizontal[0]' refers to 'commodities', which is not a field of 'goods.Apartment'.
    

    我在某个地方读到它应该足够添加 formfiled_override 要创建这样的效果,请执行以下操作:

     class ApartmentAdmin(admin.ModelAdmin):
        formfield_overrides = {
            models.ManyToManyField: {'widget': CheckboxSelectMultiple},
        }
    

    但这并没有改变任何事情。

    那么我该如何妥善解决这个问题呢?

    0 回复  |  直到 3 年前
        1
  •  0
  •   ufk    3 年前

    好吧,django可以比我所知道的更多地在幕后自动化:)

    首先,我创建了一个从公寓模型到商品模块的多对多关系:

    class Apartment(models.Model):
    ...
        commodities = models.ManyToManyField(Commodities)
    ...
    

    我删除 CommoditiesModelForm 我试图合作的,也被删除了 ApartmentCommodities 自那以后的模型 models.ManyToManyField 正在幕后为我创建类似的东西,我也不需要内联 ApartmentCommoditiesInline 到管理模块。

    现在,当公寓模式确实有多对多的关系时,我可以使用 formfield_overrides 在上面:

    class ApartmentAdmin(admin.ModelAdmin):
        formfield_overrides = {
            models.ManyToManyField: {'widget': CheckboxSelectMultiple},
        }
    

    就这样:)