Django Adminでフィールドのサイズを変更する


107

Djangoは、adminでエントリを追加または編集するときに水平方向のスペースを埋める傾向がありますが、場合によっては、日付フィールド、幅8文字、またはCharField(6または8)を編集するときに、スペースを無駄にすることがあります文字幅が広い場合、編集ボックスは最大15文字または20文字になります。

テキストボックスの幅、またはテキストフィールド編集ボックスの高さを管理者に伝えるにはどうすればよいですか?


9
明らかに、あなたはこの場合それをするのを忘れていました。2年以上後。=)
casperOne 2012年

プロジェクトが廃止され、しばらくコードを見る必要がなくなりました。私は来月新しいプロジェクトを始めるかもしれないので、多分私はこれを再びやるだろう:D
Andor

回答:


209

ModelAdmin.formfield_overridesを使用する必要があります。

それは非常に簡単です-でadmin.py、定義します:

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

class YourModelAdmin(admin.ModelAdmin):
    formfield_overrides = {
        models.CharField: {'widget': TextInput(attrs={'size':'20'})},
        models.TextField: {'widget': Textarea(attrs={'rows':4, 'cols':40})},
    }

admin.site.register(YourModel, YourModelAdmin)

1
これは、とんでもないテンプレートのカスタマイズを行わなくても、まさに私が探していたものでした。ありがとう!
Chris

2
これは動作しないことに注意してください filter_horizontalfilter_verticalYourModelAdminの対応するフィールドのために設定されています。私はこれを理解するのに少し時間を費やしました。
Dennis Golomazov 2013

フォームでこれに不利な点はありますか?すべてのTextareaにattrs属性を設定する方法が見つかりませんでした。
ジュリアン

1
使用しただけですmodels.TextField: {'widget': Textarea(attrs={'rows':4})}が幅も狭くなりました。
スミットジョンス2018年

一見同じサイズにするのは難しいです。
ソレン

44

「attrs」プロパティを使用して、ウィジェットに任意のHTML属性を設定できます

これは、Django管理でformfield_for_dbfieldを使用して行うことができます。

class MyModelAdmin(admin.ModelAdmin):
  def formfield_for_dbfield(self, db_field, **kwargs):
    field = super(ContentAdmin, self).formfield_for_dbfield(db_field, **kwargs)
    if db_field.name == 'somefield':
      field.widget.attrs['class'] = 'someclass ' + field.widget.attrs.get('class', '')
    return field

または、カスタムウィジェットサブクラスとformfield_overrides辞書を使用します。

class DifferentlySizedTextarea(forms.Textarea):
  def __init__(self, *args, **kwargs):
    attrs = kwargs.setdefault('attrs', {})
    attrs.setdefault('cols', 80)
    attrs.setdefault('rows', 5)
    super(DifferentlySizedTextarea, self).__init__(*args, **kwargs)

class MyModelAdmin(admin.ModelAdmin):
  formfield_overrides = { models.TextField: {'widget': DifferentlySizedTextarea}}

29

特定のフィールドの幅を変更します。

介して行わModelAdmin.get_form

class YourModelAdmin(admin.ModelAdmin):
    def get_form(self, request, obj=None, **kwargs):
        form = super(YourModelAdmin, self).get_form(request, obj, **kwargs)
        form.base_fields['myfield'].widget.attrs['style'] = 'width: 45em;'
        return form

私の意見では、これは最良の答えです。新しいフォームを作成する必要なく個々のフィールドを変更できるからです。
rbennell 2017

20

すばやく簡単な方法は、問題のモデルにカスタムテンプレートを提供することです。

という名前のテンプレートを作成するとadmin/<app label>/<class name>/change_form.html、管理者はデフォルトではなくそのテンプレートを使用します。つまり、という名前Personのアプリでという名前のモデルがある場合people、という名前のテンプレートを作成しますadmin/people/person/change_form.html

すべての管理テンプレートには、にデータextraheadを配置するためにオーバーライドできるブロックが<head>あり、パズルの最後のピースは、すべてのフィールドにHTML IDがあることid_<field-name>です。

したがって、テンプレートに次のようなものを入れることができます:

{% extends "admin/change_form.html" %}

{% block extrahead %}
  {{ block.super }}
  <style type="text/css">
    #id_my_field { width: 100px; }
  </style>
{% endblock %}

ありがとう!これとalanjdsによる回答は、フィールドタイプごとではなく、フィールドごとに管理インターフェイスのレイアウトを変更する場合に非常に役立ちます。
nealmcb 14

10

フィールドごとのインスタンスの属性を変更する場合は、「attrs」プロパティをフォームエントリに直接追加できます。

例えば:

class BlogPostForm(forms.ModelForm):
    title = forms.CharField(label='Title:', max_length=128)
    body = forms.CharField(label='Post:', max_length=2000, 
        widget=forms.Textarea(attrs={'rows':'5', 'cols': '5'}))

    class Meta:
        model = BlogPost
        fields = ('title', 'body')

「attrs」プロパティは基本的に、フォームフィールドを調整するHTMLマークアップを渡します。各エントリは、オーバーライドしたい属性とオーバーライドしたい値のタプルです。各タプルをコンマで区切る限り、必要なだけ属性を入力できます。


IMOは、一度にすべてのTextInputウィジェットを変更するのではなく、単一のフィールドのみを変更するための最良の方法(承認された回答のように)
ascripter

7

私が見つけた最良の方法は次のようなものです:

class NotificationForm(forms.ModelForm):
    def __init__(self, *args, **kwargs): 
        super(NotificationForm, self).__init__(*args, **kwargs)
        self.fields['content'].widget.attrs['cols'] = 80
        self.fields['content'].widget.attrs['rows'] = 15
        self.fields['title'].widget.attrs['size'] = 50
    class Meta:
        model = Notification

そのそれは保存して、より良いのModelFormに異なるウィジェットでフィールドを上書きするよりもはるかにname及びhelp_text属性と、モデルフィールドのデフォルト値は、あなたのフォームにコピーする必要はありませんので。


7

TextFieldにも同様の問題がありました。私はDjango 1.0.2を使用しており、関連するtextareaの「行」のデフォルト値を変更したいと考えています。formfield_overridesはこのバージョンには存在しません。formfield_for_dbfieldのオーバーライドは機能しましたが、ModelAdminサブクラスごとに行う必要がありました。そうしないと、再帰エラーが発生しました。最終的に、以下のコードをmodels.pyに追加すると機能することがわかりました。

from django.forms import Textarea

class MyTextField(models.TextField):
#A more reasonably sized textarea                                                                                                            
    def formfield(self, **kwargs):
         kwargs.update(
            {"widget": Textarea(attrs={'rows':2, 'cols':80})}
         )
         return super(MyTextField, self).formfield(**kwargs)

次に、モデルを定義するときに、TextFieldの代わりにMyTextFieldを使用します。私はこの答えからそれを同様の質問に適応させました。


5

Django FAQでよく説明されています:

Q:モデルのフィールドのウィジェットの属性を変更するにはどうすればよいですか?

A: ModelAdmin / StackedInline / TabularInlineクラスのformfield_for_dbfieldをオーバーライドします

class MyOtherModelInline(admin.StackedInline):
    model = MyOtherModel
    extra = 1

    def formfield_for_dbfield(self, db_field, **kwargs):
        # This method will turn all TextFields into giant TextFields
        if isinstance(db_field, models.TextField):
            return forms.CharField(widget=forms.Textarea(attrs={'cols': 130, 'rows':30, 'class': 'docx'}))
        return super(MyOtherModelInline, self).formfield_for_dbfield(db_field, **kwargs)

この手法を使用すると、ヘルプテキストが表示されず、TabularInlineの場合、列ヘッダーは「なし」になります。
スティーブンT.スナイダー

1
CharFieldの他のすべての設定を消去するため、これは良い方法ではありません。たとえば、デフォルトでは、フォームフィールドが必要かどうかをインテリジェントに検出しますが、このコードはそれを破棄します。代わりに、super()呼び出しによって返された値にウィジェットを設定する必要があります。
セリン

5

いつでもカスタムスタイルシートでフィールドサイズを設定し、DjangoにそれをModelAdminクラスに使用するように指示できます。

class MyModelAdmin(ModelAdmin):
    class Media:
        css = {"all": ("my_stylesheet.css",)}

ベストアンサー!フォームフィールドと属性(および考えられる副作用)をいじる必要はありません。CSSファイルだけです。これは、django管理フォームの既存のID /クラスを使用して、一部またはすべてのフィールドのみを簡単にターゲットにすることができます。ビッグアップ!
ベンクジ2017年

2

1.6では、フォームを使用して、charfield内のtextareaの属性を指定する必要がありました。

test1 = forms.CharField(max_length=400, widget=forms.Textarea( attrs={'rows':'2', 'cols': '10'}),  initial='', help_text=helptexts.helptxt['test'])

1

msdinと同じ答えですが、TextAreaの代わりにTextInputを使用します。

from django.forms import TextInput

class ShortTextField(models.TextField):
    def formfield(self, **kwargs):
         kwargs.update(
            {"widget": TextInput(attrs={'size': 10})}
         )
         return super(ShortTextField, self).formfield(**kwargs)

1

シンプルでありながら柔軟なソリューションを次に示します。カスタムフォームを使用して一部のウィジェットをオーバーライドします。

# models.py
class Elephant(models.Model):
    name = models.CharField(max_length=25)
    age = models.IntegerField()

# forms.py
class ElephantForm(forms.ModelForm):

    class Meta:
        widgets = {
            'age': forms.TextInput(attrs={'size': 3}),
        }

# admin.py
@admin.register(Elephant)
class ElephantAdmin(admin.ModelAdmin):
    form = ElephantForm

に記載されているウィジェットElephantFormは、デフォルトのウィジェットを置き換えます。キーはフィールドの文字列表現です。フォームで指定されていないフィールドは、デフォルトのウィジェットを使用します。

が、そのノートageであるIntegerField私たちが使用できるTextInputとは違っているので、ウィジェットをNumberInputTextInput受け入れるsize属性を。

このソリューションについては、この記事で説明します


0

選択肢/オプション/ドロップダウンメニューを含むForeignKeyフィールドを使用formfield_for_foreignkeyしている場合は、管理インスタンスでオーバーライドできます。

class YourNewAdmin(admin.ModelAdmin):
    ...

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == 'your_fk_field':
            """ For your FK field of choice, override the dropdown style """
            kwargs["widget"] = django.forms.widgets.Select(attrs={
                'style': 'width: 250px;'
            })

        return super().formfield_for_foreignkey(db_field, request, **kwargs)

このパターンの詳細については、こちらこちらをご覧ください


-1

そしてもう1つの例:

class SecenekInline(admin.TabularInline):
   model = Secenek
   # classes = ['collapse']
   def formfield_for_dbfield(self, db_field, **kwargs):
       field = super(SecenekInline, self).formfield_for_dbfield(db_field, **kwargs)
       if db_field.name == 'harf':
           field.widget = TextInput(attrs={'size':2})
       return field
   formfield_overrides = {
       models.TextField: {'widget': Textarea(attrs={'rows':2})},
   }
   extra = 2

特定のフィールドサイズのみを編集する場合は、これを使用できます。

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