Django:使用mptt-django将产品分配给多对多关系中的类别

时间:2017-07-26 08:30:37

标签: django django-mptt

我在产品和类别之间存在多对多的关系。我正在使用mpt来管理管理员上的类别显示(工作正常),因此我可以将产品分配到类别。

虽然这些类别工作正常但是我遇到问题的产品方面。

在我的models.py中(为了简洁而截断):

from mptt.models import MPTTModel,TreeForeignKey,TreeManyToManyField

class ProductCategory(MPTTModel):
    parent = TreeForeignKey('self', null=True, blank=True)

class Product(models.Model)
    categories = TreeManyToManyField(ProductCategory)

在我的admin.py中我有

from django.forms import CheckboxSelectMultiple
from .models import Product,ProductCategory
from django.db import models
from django.contrib import admin
from mptt.admin import MPTTModelAdmin
from mptt.models import TreeManyToManyField

class ProductAdmin(admin.ModelAdmin):

   formfield_overrides = {
      TreeManyToManyField:{'widget':CheckboxSelectMultiple},
   }

这几乎完成了工作,但所有类别都显示了复选框,这不是我想要的,因为您不想将产品添加到具有子类别的类别。

enter image description here

我想要的是显示类别,这样您只能将产品添加到没有子项的类别中,因此在此示例中

Category 1
Category 2 sub sub 
Category 3 sub

标签将是

Category 1
Category 2 > Catgory 2 sub > Category 2 sub sub
Category 3 > Category 3 sub

非常感谢您的帮助!

更新

嗨,我意识到我的问题可能太宽泛了!

作为一个Django新手,我认为我需要做的是创建一个可能覆盖CheckboxSelectMultiple小部件的自定义小部件,我可以将其应用于我的'categories'模型属性。

目前,我正在使用如上所述的TreeManyToManyField的formfield_overrides

formfield_overrides = {
    TreeManyToManyField:{'widget':CheckboxSelectMultiple},
}

这不仅没有给出所需的结果,而且还没有为所有TreeManyToMany字段使用标准的CheckboxSelectMultiple,我可以仅为我的'categories'属性指定这个小部件吗?

尽管如此,是否可以向我展示如何创建自定义窗口小部件,传递有关类别树和选定状态的信息(对于已分配给类别的产品)?我一直试图对此进行排序,但一直在努力 - 任何帮助都非常感激!

关于KARANTSTHR评论的更新

以下是类别的截图 - 所有类别都显示没有子项的类别,但我们是否可以在标签中向父母显示这些类别,如上所述?

enter image description here

向KARANTSTHR更新2

以下是您实施的屏幕截图。

enter image description here

1 个答案:

答案 0 :(得分:2)

ModelAdmin非常灵活,您可以在ProductAdmin(表单为ModelAdmin选项)中为表单选项指定自定义ModelForm,以过滤掉没有任何子类别的类别。
所以, 我认为您不需要自定义小部件来解决您的问题,只需将 admin.py 更改为

from django import forms
from django.forms import CheckboxSelectMultiple
from .models import Product,ProductCategory
from django.contrib import admin
from mptt.admin import MPTTModelAdmin
from mptt.models import TreeManyToManyField


class filterCategories(forms.ModelForm):
    class Meta:
        model = Product
        fields = '__all__'

    def __init__(self,*args,**kwargs):
        super(filterCategories, self).__init__(*args,**kwargs)
        self.fields['categories'].queryset = ProductCategory.objects.filter(children=None)


class ProductAdmin(admin.ModelAdmin):
    form = filterCategories
    formfield_overrides = { TreeManyToManyField:{'widget':CheckboxSelectMultiple},}


admin.site.register(Product,ProductAdmin)
admin.site.register(ProductCategory,MPTTModelAdmin)


更新1
您需要在 models.py
中的ProductCategory类的父字段中添加related_name 因此models.py中的ProductCategory类将如下所示

class ProductCategory(MPTTModel):
    name = models.CharField(max_length=100)
    parent = TreeForeignKey('self', null=True, blank=True, related_name='children')

    def __str__(self):
        return self.name

更新2
您可以更改ProductCategory的 str 方法,如标签

def __str__(self):
    try:
        ancestors = self.get_ancestors(include_self=True)
        ancestors = [i.name for i in ancestors]
    except:
        ancestors = [self.name]

    return ' > '.join(ancestors[:len(ancestors) + 1])

请注意,这不是获取您选择的标签(对象名称)的激进方法,如果我找到更好的解决方案,我会更新我的答案。