0

私はdjangoを使い始めています。私のプロジェクトでは、MPTT を使用しています。

私はかなり単純なモデルを持っています。

  • カテゴリ: (木)
  • Product1: カテゴリへの参照と外部キー。

特定の製品の基本カテゴリの検索を簡素化するために、Category モデルにルートを追加しました

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(Category, limit_choices_to = {root : '製品の一部のカテゴリ'})

もちろん、これは不可能ですが、私が望むものを示しています。

TreeChoiseField をフィルタリングして、モデルのプロパティ (この場合はルート) に基づいていくつかのブランチのみを表示できるようにしたいと考えています。

ありがとう

4

1 に答える 1

0

多くのスクランブルの後、私は解決策を見つけました。これが最善の方法だとは思いませんが、私が見る限り、うまくいきます。

mptt TreeNodeChoiceField をオーバーロードし、TreeForeignKeyFiltered をコピーしました

製品では、 foreingkey を変更しました

カテゴリ = TreeForeignKeyFiltered(カテゴリ、ルート = 'マザーボード')

root キーワードを 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)

これで、キーワード root を foreingkey に渡すことができます。これにより、管理フォームの可能性がフィルタリングされます。

繰り返しますが、これが最善の方法であるかどうかはわかりません。もちろん、それはきれいにすることができます....

于 2013-01-31T19:31:50.680 に答える