2013-01-31 68 views
0

我开始使用django。 在我的项目中,我使用MPTT。mptt TreeNodeChoiceField已过滤

我有一个相当简单的模型。

  • 类别:(树)
  • 产品1:引用和外键的类别。

我添加根部到分类模型,只是为了简化用于基本类别寻找一个特定的产品

models.py

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

    @property 
    def root(self): 
     return self.get_root().name 

class Product1(models.Model): 
    ref = models.CharField(max_length=200, blank=True) #YVX2311 
    category = TreeForeignKey(Category) 

admin.py

admin.site.register(Category, MPTTModelAdmin) 
admin.site.register(Product) 

我想修改管理表单,以便能够说出类似的内容。

models.ForeignKey(分类,limit_choices_to = {根: '有些 类别产品1'})

当然,这是不可能的,但它确实说明了我想要的东西。

我希望能够过滤TreeChoiseField,只显示一些基于模型属性(本例中为root)的分支。

谢谢

回答

0

经过多次争论,我找到了一个解决方案。 我不认为这是做到这一点的最佳方式,但据我所见,它的工作原理。

我重载MPTT TreeNodeChoiceField和复制的TreeForeignKeyFiltered

在产品上,我改变了foreingkey为

类别= TreeForeignKeyFiltered(分类,根='主板的)

我将根关键字添加到TreeForeingKeyFiltered

class TreeForeignKeyFiltered(models.ForeignKey): 
    """ 
    Extends the foreign key, but uses mptt's ``TreeNodeChoiceField`` as 
    the default form field. 

    This is useful if you are creating models that need automatically 
    generated ModelForms to use the correct widgets. 
    """ 

    def __init__(self, *args, **kwargs): 
     self._root = kwargs.pop('root', None) 
     super(TreeForeignKeyFiltered, self).__init__(*args, **kwargs) 

    def formfield(self, **kwargs): 
     """ 
     Use MPTT's ``TreeNodeChoiceField`` 
     """ 
     kwargs.setdefault('root', self._root) 
     kwargs.setdefault('form_class', TreeNodeChoiceFieldFiltered) 
     return super(TreeForeignKeyFiltered, self).formfield(**kwargs) 

最后我加入了TreeNodeChoiceFieldFiltered作为

class TreeNodeChoiceFieldFiltered(TreeNodeChoiceField): 
    def __init__(self, queryset, *args, **kwargs): 
     _root = kwargs.pop('root', None) 

     if _root is not None: 
      pid = None 
      for i in queryset: 
       if i.root.name == _root: 
        pid = i.tree_id 
        break 

      if pid is not None: 
       queryset = queryset.filter(tree_id = pid) 

     super(TreeNodeChoiceFieldFiltered, self).__init__(queryset, *args, **kwargs) 

现在我可以通过关键字根将在管理表单过滤posibilities的foreingkey。

同样,我不知道这是否是最好的方法。当然它可以更清洁....