web-dev-qa-db-ja.com

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

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

どうやってやるの?

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

86
michalv82

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を編集し、上記で作成したフォームを参照するようにフォームプロパティを設定します
  2. フィールドまたはフィールドセット宣言に新しいフィールドを含めます

このような:

class YourModelAdmin(admin.ModelAdmin):

    form = YourModelForm

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

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

143
Vishnu

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

モデルに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)
31
gitaarik

いつでも新しい管理テンプレートを作成して、admin_viewで必要なことを行うことができます(admin add URLをadmin_viewにオーバーライドします)。

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

絶対に2つの別個のフィールドではなく、結合されたフィールドのみをモデルに保存する場合は、次のようなことができます。

私はこのようなことを一度もしなかったので、どのように機能するのか完全にはわかりません。

3
gitaarik

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__"
3
MangoLassi