django admin-モデルの一部ではないカスタムフォームフィールドを追加します


106

管理サイトにモデルを登録しています。そのフィールドの1つは長い文字列式です。カスタムフォームフィールドを管理者のこのモデルの追加/更新ページに追加します。これらのフィールドの値に基づいて、長い文字列式を作成し、関連するモデルフィールドに保存します。

どうやってやるの?

更新:基本的に私がやっていることは記号から数学または文字列式を構築し、ユーザーは記号(これらはモデルの一部ではないカスタムフィールドです)を選択し、保存をクリックしてから文字列式表現を作成しますシンボルのリストを作成し、DBに保存します。シンボルがモデルとDBの一部になりたくないので、最終的な式のみです。

回答:


156

admin.pyまたは別のforms.pyのいずれかで、ModelFormクラスを追加し、通常どおりにその中に追加のフィールドを宣言できます。form.save()でこれらの値を使用する方法の例も示しました。

from django import forms
from yourapp.models import YourModel


class YourModelForm(forms.ModelForm):

    extra_field = forms.CharField()

    def save(self, commit=True):
        extra_field = self.cleaned_data.get('extra_field', None)
        # ...do something with extra_field here...
        return super(YourModelForm, self).save(commit=commit)

    class Meta:
        model = YourModel

管理者に追加フィールドを表示するには、次のようにします。

  1. admin.pyを編集し、上で作成したフォームを参照するようにformプロパティを設定します
  2. フィールドまたはフィールドセット宣言に新しいフィールドを含める

このような:

class YourModelAdmin(admin.ModelAdmin):

    form = YourModelForm

    fieldsets = (
        (None, {
            'fields': ('name', 'description', 'extra_field',),
        }),
    )

更新:django 1.8ではfields = '__all__'、YourModelFormのメタクラスに追加する必要があります。


2
はい、私は本当に理由を知りたいです
Vishnu

13
あなたは追加する必要がありfields = '__all__'、あなたにMetaそうジャンゴ不平を言い、クラス:Creating a ModelForm without either the 'fields' attribute or the 'exclude' attribute is deprecated
IsaacKleiner

1
@sthzg、それが正しくないから。それは私にエラーを与えます:YourModelAdmin.list_display[0], 'extra_field' is not a callable or an attribute of 'YourModelAdmin' or found in the model 'YourModel'.
Cerin

7
何らかの理由でを取得した場合は、定義にをAttributeError: Unable to lookup "extra_field"...追加しlabelてみてextra_fieldください。django ModelModelAdmin、そのような属性定義のとを見て、ラベルを「推測」しようとしているようです。
alxs

1
これは、extra_fieldがCharField()である場合に美しく機能しました。ただし、hiddenFieldの場合(Django 1.11では)、エラーが生成されUnknown field(s) (extra_field) specified for YourModel. Check fields/fieldsets/exclude attributes of class YourModelAdmin.ます。そのための回避策はextra_field = forms.CharField(widget=forms.HiddenInput())
kakoma 2018年

35

管理で行うことは可能ですが、非常に簡単な方法はありません。また、Django管理者に依存しないように、モデルにほとんどのビジネスロジックを保持することをお勧めします。

モデルに2つの別々のフィールドがある場合は、おそらくそれがより簡単になります(さらにはさらに優れているかもしれません)。次に、それらを組み合わせるメソッドをモデルに追加します。

例えば:

class MyModel(models.model):

    field1 = models.CharField(max_length=10)
    field2 = models.CharField(max_length=10)

    def combined_fields(self):
        return '{} {}'.format(self.field1, self.field2)

次に、管理者でcombined_fields()読み取り専用フィールドとして追加できます:

class MyModelAdmin(models.ModelAdmin):

    list_display = ('field1', 'field2', 'combined_fields')
    readonly_fields = ('combined_fields',)

    def combined_fields(self, obj):
        return obj.combined_fields()

combined_fieldsデータベースに保存する場合は、モデルを保存するときにも保存できます。

def save(self, *args, **kwargs):
    self.field3 = self.combined_fields()
    super(MyModel, self).save(*args, **kwargs)

4
答えてくれてありがとう、でもこれは私が探しているものではありません。カスタムフィールドをDBに保存したくありません。計算された文字列だけを保存します。基本的に私がやっていることは、記号から数学または文字列式を構築し、ユーザーが記号(これらはモデルの一部ではないカスタムフィールドです)を選択し、保存をクリックすると、リストの文字列式表現を作成しますシンボルを作成し、DBに保存します。
michalv82 2013

@ michalv82モデルのsave()メソッドでデータベースに保存することもできます。私の回答の更新を確認してください。
gitaarik 2013

1
もう一度感謝しますが、問題は、最後のフィールド(つまり、シンボル)を組み合わせるフィールドを保存したくないということです。最終的な文字列を保存するだけです
michalv82

2つのフィールドを保存することは問題ですか?結合されたフィールドがどのように生成されたかを知りたい場合は、おそらく重宝するでしょう。
gitaarik 2013

6
改めて感謝しますが、2つのフィールドではありません。繰り返しますが、私はそれらをDBに保存したくないので、この解決策は私にはうまくいきません。
michalv82 2013

5

Django 2.1.1第一の答えは、私の質問に答える途中でした。実際のモデルのフィールドに結果を保存するのに役立ちませんでした。私の場合、ユーザーがデータを入力できるテキストフィールドが必要でしたが、保存が発生すると、データが処理され、結果がモデルのフィールドに入力されて保存されました。元の答えは追加フィールドから値を取得する方法を示しましたが、少なくともDjango 2.1.1ではモデルに値を保存する方法を示していませんでした

これは、バインドされていないカスタムフィールドから値を取得して処理し、実際の説明フィールドに保存します。

class WidgetForm(forms.ModelForm):
    extra_field = forms.CharField(required=False)

    def processData(self, input):
        # example of error handling
        if False:
            raise forms.ValidationError('Processing failed!')

        return input + " has been processed"

    def save(self, commit=True):
        extra_field = self.cleaned_data.get('extra_field', None)

        # self.description = "my result" note that this does not work

        # Get the form instance so I can write to its fields
        instance = super(WidgetForm, self).save(commit=commit)

        # this writes the processed data to the description field
        instance.description = self.processData(extra_field)

        if commit:
            instance.save()

        return instance

    class Meta:
        model = Widget
        fields = "__all__"

4

いつでも新しい管理テンプレートを作成し、admin_viewで必要なことを実行できます(adminのadmin_viewへのURLを上書きします)。

 url(r'^admin/mymodel/mymodel/add/$' , 'admin_views.add_my_special_model')

3

2つの別々のフィールドではなく、結合されたフィールドのみをモデルに保存したい場合は、次のようにします。

私はこのようなことをしたことがないので、それがどのように機能するかは完全にはわかりません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.