47

注文は複数の注文に分割できるため、自動インクリメントの主キーと外部キーを備えたWebショップアプリケーションの注文のモデルがありますが、元の注文との関係を維持する必要があります。

class Order(models.Model):
    ordernumber = models.AutoField(primary_key=True)
    parent_order = models.ForeignKey('self', null=True, blank=True, related_name='child_orders')
    # .. other fields not relevant here

管理サイトのOrderAdminクラスを登録しました。詳細ビューについてはparent_orderfieldsets属性に含めました。もちろん、デフォルトでは、これは選択ボックスにすべての注文をリストしますが、これは望ましい動作ではありません。代わりに、親注文がない(つまり、別の注文から分割されていない、parent_orderNULL /なし)注文の場合、注文は表示されません。分割された注文の場合、これは単一の親注文のみを表示する必要があります。

かなり新しいModelAdminメソッドが利用可能です。これは、クエリセットformfield_for_foreignkeyを内部でフィルタリングできるため、これに最適のようです。注文番号11208から分割された注文番号11234の詳細ビューを見ていると想像してください。コードは以下のとおりです

def formfield_for_foreignkey(self, db_field, request, **kwargs):
    if db_field.name == 'parent_order':
        # kwargs["queryset"] = Order.objects.filter(child_orders__ordernumber__exact=11234)
        return db_field.formfield(**kwargs)
    return super(OrderAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)

コメント付きの行は、Pythonシェルで実行すると機能し、#11234の注文#11208と、そこから分割された可能性のある他のすべての注文を含む単一アイテムのクエリセットを返します。

もちろん、そこで注文番号をハードコーディングすることはできません。ordernumber詳細ページを表示している注文インスタンスのフィールドへの参照が必要です。このような:

kwargs["queryset"] = Order.objects.filter(child_orders__ordernumber__exact=?????)

置き換えるための有効な方法が見つかりませんか????? 「現在の」Orderインスタンスを参照して、かなり深く掘り下げました。self内部formfield_for_foreignkeyはModelAdminインスタンスを参照し、model属性はありますが、注文モデルインスタンスではありません(ModelBase参照です。self.model()はインスタンスを返しますが、注文番号はNoneです)。

1つの解決策は、request.path(/ admin /orders / order / 11234 /)から注文番号を取得することかもしれませんが、それは本当に醜いです。もっと良い方法があると本当にいいのですが。

4

3 に答える 3

61

adminクラスではなく、ModelFormを変更するなど、少し異なる方法でこれに取り組む必要があると思います。このようなもの:

class OrderForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        super(OrderForm, self).__init__(*args, **kwargs)
        self.fields['parent_order'].queryset = Order.objects.filter(
            child_orders__ordernumber__exact=self.instance.pk)

class OrderAdmin(admin.ModelAdmin):
    form = OrderForm
于 2009-06-04T08:37:34.157 に答える
9

インラインクラスをこのようにモデル化しました。インラインデータをフィルタリングするために親フォームIDを取得する方法については少し醜いですが、機能します。親フォームから会社ごとにユニットをフィルタリングします。

元の概念はここで説明されていますhttp://www.stereoplex.com/blog/filtering-dropdown-lists-in-the-django-admin

class CompanyOccupationInline(admin.TabularInline):

    model = Occupation
    # max_num = 1
    extra = 0
    can_delete = False
    formset = RequiredInlineFormSet

    def formfield_for_dbfield(self, field, **kwargs):

        if field.name == 'unit':
            parent_company = self.get_object(kwargs['request'], Company)
            units = Unit.objects.filter(company=parent_company)
            return forms.ModelChoiceField(queryset=units)
        return super(CompanyOccupationInline, self).formfield_for_dbfield(field, **kwargs)

    def get_object(self, request, model):
        object_id = resolve(request.path).args[0]
        try:
            object_id = int(object_id)
        except ValueError:
            return None
        return model.objects.get(pk=object_id)
于 2012-04-03T02:37:10.923 に答える
3

Erwin Juliusからの上記の回答は、「get_object」という名前がDjango関数と競合することがわかったので、関数に「my_get_object」という名前を付けることを除いて、私にとってはうまくいきました。

class CompanyOccupationInline(admin.TabularInline):

    model = Occupation
    # max_num = 1
    extra = 0
    can_delete = False
    formset = RequiredInlineFormSet

    def formfield_for_dbfield(self, field, **kwargs):

        if field.name == 'unit':
            parent_company = self.my_get_object(kwargs['request'], Company)
            units = Unit.objects.filter(company=parent_company)
            return forms.ModelChoiceField(queryset=units)
        return super(CompanyOccupationInline, self).formfield_for_dbfield(field, **kwargs)

    def my_get_object(self, request, model):
        object_id = request.META['PATH_INFO'].strip('/').split('/')[-1]
        try:
            object_id = int(object_id)
        except ValueError:
            return None
        return model.objects.get(pk=object_id)

他人の答えに「返事」しないように言われましたが、まだ「返事」は許されておらず、しばらく探していたので、他人の役に立つことを願っています。私もまだ賛成することは許されていません。

于 2013-10-29T21:21:37.797 に答える