Django-管理者:TextAreaとしてのCharField


88

私は持っています

class Cab(models.Model):
    name  = models.CharField( max_length=20 )
    descr = models.CharField( max_length=2000 )

class Cab_Admin(admin.ModelAdmin):
    ordering     = ('name',)
    list_display = ('name','descr', )
    # what to write here to make descr using TextArea?

admin.site.register( Cab, Cab_Admin )

TextAreaウィジェットを管理インターフェースの「descr」フィールドに割り当てる方法は?

UPD:
管理インタフェースだけ!

ModelFormを使用することをお勧めします。


3
受け入れられた答えは、たった1つのフィールドを変更するための巨大なやり過ぎです!人々は、簡略化のためカール・マイヤーによってこの答えは、次のとおりstackoverflow.com/questions/430592/...
andilabs

回答:


99

フィールドをforms.ModelFormどのdescrように表示するかを説明するを作成してadmin.ModelAdminから、そのフォームを使用するように指示する必要があります。例えば:

from django import forms
class CabModelForm( forms.ModelForm ):
    descr = forms.CharField( widget=forms.Textarea )
    class Meta:
        model = Cab

class Cab_Admin( admin.ModelAdmin ):
    form = CabModelForm

form属性はadmin.ModelAdmin、Djangoの公式ドキュメントに記載されています。ここに1つの場所があります


6
フォームウィジェットを単に置き換えるために、独自のフォーム全体を作成する必要はありません。あなたはただあなたを上書きすることができformfield_for_dbfieldますModelAdmin、以下の私の答えを見てください。
カールマイヤー

1
これによりdjango.core.exceptions.ImproperlyConfigured: Creating a ModelForm without either the 'fields' attribute or the 'exclude' attribute is prohibited
John Wu

4
Django 1.7以降、のfields = '__all__'下にも追加する必要がありますclass Meta:
skoll 2016年

2
フォームを自分で作成する必要はありませんget_form。メソッドをオーバーライドできます。私の答えを参照しください。
x-yuri 2018年

ビーターのアプローチは、メタクラスを使用することです。メタ:モデル=メッセージウィジェット= {'テキスト':forms.Textarea(attrs = {'cols':80、 '行':20})、}
AmulyaAcharya19年

58

この場合、おそらく最良のオプションは、モデルでCharFieldの代わりにTextFieldを使用することです。クラスのformfield_for_dbfieldメソッドをオーバーライドすることもできますModelAdmin

class CabAdmin(admin.ModelAdmin):
    def formfield_for_dbfield(self, db_field, **kwargs):
        formfield = super(CabAdmin, self).formfield_for_dbfield(db_field, **kwargs)
        if db_field.name == 'descr':
            formfield.widget = forms.Textarea(attrs=formfield.widget.attrs)
        return formfield

選択した回答と比較して、これに欠点はありますか?新しいModelFormを作成する必要がないため、これは実装がよりクリーンに見えます...
Filipe Pina 2012

3
TextFieldに対して自動的に生成されたすべての属性を保持するために、に置き換えられformfield.widget = forms.Textarea()ましformfield.widget = forms.Textarea(attrs=formfield.widget.attrs)た。ありがとうございます。
Filipe Pina 2012

2
なぜ他の答えがこれよりも受け入れられるのかわかりません。ウィジェットを置き換えるだけなら、これはもっと簡単だと思います。しかし、どちらでも問題なく動作します。
カールマイヤー

おかげで、これは完璧に機能しました。super()の呼び出しは少し冗長に見えますが、もっと簡単な方法はありますか?
rjh 2015

2
@rjh py3では、parens内のすべてを削除して、を使用することができますsuper()。それ以外の場合はありません。
カールマイヤー

33

Ayazは、わずかな変更(?!)を除いて、ほとんど注目を集めています。

class MessageAdminForm(forms.ModelForm):
    class Meta:
        model = Message
        widgets = {
            'text': forms.Textarea(attrs={'cols': 80, 'rows': 20}),
        }

class MessageAdmin(admin.ModelAdmin):
    form = MessageAdminForm
admin.site.register(Message, MessageAdmin)

したがって、ウィジェットを変更するためにModelFormのフィールドを再定義する必要はなく、メタでウィジェットのdictを設定するだけです。


1
これは、Ayazの回答よりも多くの「自動」プロパティを保持しますが、フィールド長の検証を維持する方法に関するヒントもありますか?
Filipe Pina 2012

14

必要なformfieldメソッドを使用して、独自のフィールドをサブクラス化できます。

class CharFieldWithTextarea(models.CharField):

    def formfield(self, **kwargs):
        kwargs.update({"widget": forms.Textarea})
        return super(CharFieldWithTextarea, self).formfield(**kwargs)

これは、生成されたすべてのフォームに影響します。


9

フォームクラスを自分で作成する必要はありません。

from django.contrib import admin
from django import forms

class MyModelAdmin(admin.ModelAdmin):
    def get_form(self, request, obj=None, **kwargs):
        kwargs['widgets'] = {'descr': forms.Textarea}
        return super().get_form(request, obj, **kwargs)

admin.site.register(MyModel, MyModelAdmin)

ModelAdmin.get_formを参照してください。


7

の代わりに、forをmodels.CharField使用models.TextFielddescrます。


4
残念ながら、max_length =はTextFieldのDjangoによって完全に無視されるため、フィールド長の検証が必要な場合(秘書にイベントの概要を入力させるなど)、それを取得する唯一の方法はCharFieldを使用することです。しかし、CharFieldは、300文字を入力するための短縮方法です。したがって、ayazソリューション。
シャッカー2009

3
これはデータベースを変更するため、良い答えではありません。ウィジェットを変更するポイントは、データベーススキーマを変更するのではなく、フィールドの表示方法を変更することです

1
これは、Djangoの使用方法を学んでいて、私がもっとよく知っていれば、そもそもデータベースを別の方法でセットアップしていただろう誰か(私のような)にとって素晴らしい答えです。
Andrew Swift

7

admin.pyのTextareaを変更しようとしている場合、これは私のために働いた解決策です:

from django import forms
from django.contrib import admin
from django.db import models
from django.forms import TextInput, Textarea

from books.models import Book

class BookForm(forms.ModelForm):
    description = forms.CharField( widget=forms.Textarea(attrs={'rows': 5, 'cols': 100}))
    class Meta:
        model = Book

class BookAdmin(admin.ModelAdmin):
    form = BookForm

admin.site.register(Book, BookAdmin)

MySQL DBを使用している場合、列の長さは通常250文字に自動設定されるため、ALTER TABLEを実行してMySQLDBの長さを変更し、新しい大きなTextareaを利用できるようにします。 AdminDjangoサイトがあります。


5

models.TextFieldこの目的で使用できます。

class Sample(models.Model):
    field1 = models.CharField(max_length=128)
    field2 = models.TextField(max_length=1024*2)   # Will be rendered as textarea

3
これによりDB構造が変更されるため、注意してください
elad silver 2018

3

この日付まで完全に機能するCarlMeyerの回答を拡張したかった。

私は常にTextField代わりにCharField(選択の有無にかかわらず)使用し、DBレベルではなくUI / API側に文字制限を課します。これを動的に機能させるには:

from django import forms
from django.contrib import admin


class BaseAdmin(admin.ModelAdmin):
    """
    Base admin capable of forcing widget conversion
    """
    def formfield_for_dbfield(self, db_field, **kwargs):
        formfield = super(BaseAdmin, self).formfield_for_dbfield(
            db_field, **kwargs)

        display_as_charfield = getattr(self, 'display_as_charfield', [])
        display_as_choicefield = getattr(self, 'display_as_choicefield', [])

        if db_field.name in display_as_charfield:
            formfield.widget = forms.TextInput(attrs=formfield.widget.attrs)
        elif db_field.name in display_as_choicefield:
            formfield.widget = forms.Select(choices=formfield.choices,
                                            attrs=formfield.widget.attrs)

        return formfield

、&がsで、選択肢があるモデル名Postがあります。管理者の定義は次のようになります。titleslugstateTextFieldstate

@admin.register(Post)
class PostAdmin(BaseAdmin):
    list_display = ('pk', 'title', 'author', 'org', 'state', 'created',)
    search_fields = [
        'title',
        'author__username',
    ]
    display_as_charfield = ['title', 'slug']
    display_as_choicefield = ['state']

答えを探している他の人がこれが役に立つかもしれないと思った。


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