5

Django Grappelli 管理ツールを使用して、次のように、ForeignKey (多対 1) フィールドをドロップダウン フィールドではなくオートコンプリート ウィジェットとして表示するように構成できます。

class MyModel(models.Model):
    related = models.ForeignKey(RelatedModel, related_name='my_models')

class MyModelAdmin(admin.ModelAdmin):
    raw_id_fields = ('related',)
    autocomplete_lookup_fields = {
        'fk': ['related'],
    }

しかし、私がやりたいのは、他の(1 対多) 方向 (つまり、RelatedModel の管理で、1つ以上の MyModel オブジェクトを検索できるようにするため) のオートコンプリート ウィジェット ルックアップを定義することです。今、私は ModelMultipleChoiceField を使用しています:

class RelatedModelForm(forms.ModelForm):
    class Meta:
        model = RelatedModel
        fields = ('my_models',)
    my_models = forms.ModelMultipleChoiceField(queryset=MyModel.objects.all())

    def __init__(self, *args, **kwargs):
        super(SaleAdminForm, self).__init__(*args, **kwargs)
        if self.instance:
            self.fields['foods'].initial = self.instance.foods.all()

    def save(self, *args, **kwargs):
        instance = super(RelatedModelForm, self).save(commit=False)
        self.fields['my_models'].initial.update(related=None)
        self.cleaned_data['my_models'].update(related=instance)
        return instance

class RelatedModelAdmin(admin.ModelAdmin):
    model = RelatedModel
    form = RelatedModelForm

ただし、そのタイプのウィジェットでうまく機能するには MyModel インスタンスが多すぎます。ModelMultipleChoiceField の代わりに、MyModel オブジェクトのオートコンプリート ルックアップ ウィジェットを 1 つ以上用意するのが理想的です。

Grappelli には、FK リレーションと m2m リレーションのオートコンプリート ルックアップを作成する簡単な方法がありますが、1 対多リレーションの方法はありますか? これらのオートコンプリートは、他の 2 種類のリレーションと同じように役立つように思われるので、Grappelli はそこでも簡単な方法を提供すると推測していましたが、見つけられませんでした...

4

1 に答える 1

2

私が最終的にやったのは、ForeignKey フィールドを直接 RelatedModel クラスに追加して、Grappelli がページにオートコンプリートを配置できるようにすることでした。そのフィールドは何も保存するために使用されません。オートコンプリート ルックアップ用です。したがって、私のクラスは次のようになります。

class MyModel(models.Model):
    related = models.ForeignKey(RelatedModel, related_name='my_models')

class RelatedModel(models.Model):
    # Used only for autocomplete lookups in the admin (Grappelli requires that a FK or m2m relationship exists in the model).
    mockMyModel = models.ForeignKey(MyModel, verbose_name='Add a MyModel', related_name='for_mymodel_lookups')
    # my_models - implied one-to-many field

class RelatedModelAdmin(admin.ModelAdmin):
    model = RelatedModel
    form = RelatedModelAdminForm

    raw_id_fields = ('mockMyModel',)
    autocomplete_lookup_fields = {
        'fk': ['mockMyModel'],
    }

class RelatedModelAdminForm(forms.ModelForm):
    class Meta:
        model = RelatedModel
        fields = ('mockMyModel', 'my_models',)

    # Note that you need to override __init__() and save() to get this field to work.
    my_models = forms.ModelMultipleChoiceField(queryset=MyModel.objects.all(), required=False)

    def __init__(self, *args, **kwargs):
        super(RelatedModelAdminForm, self).__init__(*args, **kwargs)
        if self.instance:
            self.fields['my_models'].initial = self.instance.my_models.all()

    def save(self, *args, **kwargs):
        # TODO: Wrap reassignments into transaction
        instance = super(RelatedModelAdminForm, self).save(commit=False)
        self.fields['my_models'].initial.update(sale=None)
        self.cleaned_data['my_models'].update(sale=instance)
        return instance

上記は、ページ上のオートコンプリート ウィジェット (モック FK 関係の場合) と複数選択ウィジェット (1 対多の関係の場合) をレンダリングします。次に、複数選択フィールドをビューから非表示にし、オートコンプリート ウィジェットをハイジャックして、ユーザーが選択した各値を複数選択フィールドにコピーし、各選択後にオートコンプリートを消去する jquery プラグインを作成しました。ちょっとしたハックです... しかし、それで仕事は完了です。

于 2013-07-10T17:28:44.693 に答える