DjangoフォームでのCSSスタイル


150

次のスタイルを設定します。

forms.py:

from django import forms

class ContactForm(forms.Form):
    subject = forms.CharField(max_length=100)
    email = forms.EmailField(required=False)
    message = forms.CharField(widget=forms.Textarea)

contact_form.html:

<form action="" method="post">
  <table>
    {{ form.as_table }}
  </table>
  <input type="submit" value="Submit">
</form>

例えば、どのように私は設定しないクラスIDがためにsubjectemailmessageに外部スタイルシートを提供するには?

回答:


192

:への私の答えから取られ た<divクラス=「field_type」>ジャンゴのあるフォームフィールドをマークアップする方法

class MyForm(forms.Form):
    myfield = forms.CharField(widget=forms.TextInput(attrs={'class' : 'myfieldclass'}))

または

class MyForm(forms.ModelForm):
    class Meta:
        model = MyModel

    def __init__(self, *args, **kwargs):
        super(MyForm, self).__init__(*args, **kwargs)
        self.fields['myfield'].widget.attrs.update({'class' : 'myfieldclass'})

または

class MyForm(forms.ModelForm):
    class Meta:
        model = MyModel
        widgets = {
            'myfield': forms.TextInput(attrs={'class': 'myfieldclass'}),
        }

---編集---
上記は、元の質問のコードを変更する最も簡単な変更で、要求された内容を実行します。また、他の場所でフォームを再利用する場合に、繰り返し使用することもできません。Djangoのas_table / as_ul / as_pフォームメソッドを使用すると、クラスやその他の属性が機能します。完全にカスタムのレンダリングを完全に制御する必要がある場合、これは明確に文書化されています

-編集2 ---
ModelFormのウィジェットと属性を指定する新しい方法を追加しました。


27
ただし、プレゼンテーションとビジネスロジックを混在させることはお勧めしません。
Torsten Engelbrecht

8
このプレゼンテーションはどうですか?要素にクラスを与えます。これは単なる識別子または分類です。それでも他の場所で何をするかを定義する必要があります
shadfc '29

9
はいといいえ。最初のCSSクラスは、慣習的にスタイル設定に使用されますid。一意の識別子が必要な場合は、使用するのが適切です。2つ目は、通常、これを行うためのテンプレート側の責任です。特に、フロントエンドメソッド(js、css)を介してこのクラスにアクセスする場合。私はあなたの答えが間違っているとは言いませんでした。私の意見では、それはちょうど悪い習慣です(特に、フロントエンドとバックエンドの開発者がいるチームで作業している場合)。
Torsten Engelbrecht、2011

6
これはばかげているように見えますが、クラスを追加するためにこれだけのコードが必要ですか?これらの領域でHTML / CSSをハードコードするだけの方が簡単なようです(特にCSSが多いサイトの場合)。
David542

9
ジャンゴがこれをとてもぎこちなくするのは正気ではない!
ブライス

103

これは、カスタムテンプレートフィルターを使用して行うことができます。この方法でフォームをレンダリングすることを検討してください:

<form action="/contact/" method="post">
  {{ form.non_field_errors }}
  <div class="fieldWrapper">
    {{ form.subject.errors }}
    {{ form.subject.label_tag }}
    {{ form.subject }}
    <span class="helptext">{{ form.subject.help_text }}</span>
  </div>
</form>

form.subjectメソッドBoundFieldを持つのインスタンスですas_widget()

my_app / templatetags / myfilters.pyaddclassでカスタムフィルターを作成できます。

from django import template

register = template.Library()

@register.filter(name='addclass')
def addclass(value, arg):
    return value.as_widget(attrs={'class': arg})

次に、フィルターを適用します。

{% load myfilters %}

<form action="/contact/" method="post">
  {{ form.non_field_errors }}
  <div class="fieldWrapper">
    {{ form.subject.errors }}
    {{ form.subject.label_tag }}
    {{ form.subject|addclass:'MyClass' }}
    <span class="helptext">{{ form.subject.help_text }}</span>
  </div>
</form>

form.subjects次に、MyClassCSSクラスでレンダリングされます。


5
これは、クリーン&ソリューションを実装するのは簡単の一つである
ユーザー

5
この答えがトップの答えになるはずです!!! Djangoが提案するソリューションよりもすっきりしています。よくやった@Charlesthk
David D.

4
超役立つ。これは、最初に私には明らかではなかったが、あなたはあまりにも複数のクラスを追加するためにこれを使用することができます:{{ form.subject|addclass:'myclass1 myclass2' }}
SMG

これにより、HTMLクラスをHTMLファイルに保持できるようになります。スタイル設定をするとき、モデルやフォームではなく、スタイルシートと構造の間を行き来します。
ケビン

29

あなたが追加したくない場合は任意の(@のshadfcの回答にコメントで述べたように)コードをフォームに、それは確かに可能であるが、ここでは2つのオプションがあります。

まず、一度にフォーム全体ではなく、HTMLでフィールドを個別に参照します。

<form action="" method="post">
    <ul class="contactList">
        <li id="subject" class="contact">{{ form.subject }}</li>
        <li id="email" class="contact">{{ form.email }}</li>
        <li id="message" class="contact">{{ form.message }}</li>
    </ul>
    <input type="submit" value="Submit">
</form>

(私もそれをソートされていないリストに変更したことに注意してください。)

次に、フォームをHTMLとして出力することに関するドキュメントのDjango に注意してください:

フィールドIDは、フィールド名の前に「id_」を付加することによって生成されます。id属性とタグは、デフォルトで出力に含まれます。

すべてのフォームフィールドには既に一意のIDがあります。したがって、CSSファイルでid_subjectを参照して、件名フィールドのスタイルを設定します。これは、個々のフィールドではなく、フォームを印刷するだけのデフォルトの HTML を使用した場合のフォームの動作です。

<ul class="contactList">
    {{ form }}  # Will auto-generate HTML with id_subject, id_email, email_message 
    {{ form.as_ul }} # might also work, haven't tested
</ul>

フォームを出力するときのその他のオプションについては、前のリンクを参照してください(テーブルなどを実行できます)。

注-これは各要素にクラスを追加することと同じではないことを理解しています(フォームにフィールドを追加した場合は、CSSも更新する必要があります)-すべてのフィールドをIDで参照するのは簡単ですこのようにあなたのCSSで:

#id_subject, #id_email, #email_message 
{color: red;}

2つ目の解決策を試しましたが、うまくいきませんでした。id_emailのクラスを作成しましたが、結果を生成できませんでした。
ほぼ初心者の

@almostabeginner私がデバッグのために提案できることの1つ-ブラウザでページが表示されたら、View Page Sourceを使用して(通常は右クリックして)、Djangoが生成している実際の完全なページを確認します。必要なIDまたはクラスIDを持つフィールドが存在するかどうかを確認します。また、ほとんどのブラウザー(プラグインをインストールすることにより)は、ページに適用されているcssを表示するデバッガーを実行でき、何が起こっているかを確認するのにも役立ちます。
ジョンC

@almostabeginnerも注意して、サンプルコードを少し追加しました。テキストだけでは明確でない場合は、個々のフィールドではなくフォーム自体を参照する必要があります。その時点で、フォームはidsを含むHTMLを自動生成します。うまくいけば、それが役立ちます。
John C、

1
助けてくれてありがとう、問題は私のCSSではありませんでした、問題はキャッシュに関連していました。だから私の古いCSSは保存されていたので、どの変更も表示されませんでした。Chromeからキャッシュをクリアすると、すべてのアップデートが表示され始めました。
ほぼ初心者の

15

パーこのブログの記事は、カスタムテンプレートフィルタを使用して、フィールドにCSSクラスを追加することができます。

from django import template
register = template.Library()

@register.filter(name='addcss')
def addcss(field, css):
    return field.as_widget(attrs={"class":css})

これをアプリのtemplatetags /フォルダーに配置すると、次のことができます

{{field|addcss:"form-control"}}

2
これは、この投稿に対する実際の回答として受け入れられるはず
でした

最高のソリューションです。
Mods Vs Rockers 2017年

1
素晴らしい、ありがとう!実際にタグをロードすることを忘れないでください。また、Django 2.1では、Djangoにテンプレートを検索させる唯一の方法は、settings.py: 'libraries':{'add_css': 'app.templatetags.tag_name'、}にオプションを追加することでした
simonbogarde

11

あなたはこのようにすることができます:

class ContactForm(forms.Form):
    subject = forms.CharField(max_length=100)
    subject.widget.attrs.update({'id' : 'your_id'})

うまくいきますように。

イグナス


イグナスありがとう。正確な答え!
Rudresh Ajgaonkar

9

このライブラリを使用できます:https : //pypi.python.org/pypi/django-widget-tweaks

次のことを実行できます。

{% load widget_tweaks %}
<!-- add 2 extra css classes to field element -->
{{ form.title|add_class:"css_class_1 css_class_2" }}

1
Charlesthkソリューションを見てください。追加のライブラリを追加しなくても同じです:)
David D.

@DavidW .:はい。ただし、ウィジェットツイークにはのような多くのフィルターがありますrender_field
mrdaliri 2014年

5

できるよ:

<form action="" method="post">
    <table>
        {% for field in form %}
        <tr><td>{{field}}</td></tr>
        {% endfor %}
    </table>
    <input type="submit" value="Submit">
</form>

次に、クラス/ IDを<td>タグなどに追加できます。もちろん、他の任意のタグを使用できます。Djangoフォームでの作業の例として、フォームで使用できるものを確認してくださいfield{{field}}たとえば、ラベルではなく、入力タグを出力するだけです)。


3

1つの解決策は、ページの準備が整った後にJavaScriptを使用して必要なCSSクラスを追加することです。たとえば、ブートストラップクラスでのdjangoフォーム出力のスタイル設定(簡潔にするためにjQueryを使用):

<script type="text/javascript">
    $(document).ready(function() {
        $('#some_django_form_id').find("input[type='text'], select, textarea").each(function(index, element) {
            $(element).addClass("form-control");
        });
    });
</script>

これにより、スタイリングの詳細とビジネスロジックを混在させる醜さを回避できます。


3

次のようにフォームを記述します。

    class MyForm(forms.Form):
         name = forms.CharField(widget=forms.TextInput(attr={'class':'name'}),label="Your Name")
         message = forms.CharField(widget=forms.Textarea(attr={'class':'message'}), label="Your Message")

HTMLフィールドで次のようにします。

{% for field in form %}
      <div class="row">
        <label for="{{ field.name}}">{{ field.label}}</label>{{ field }}
     </div>
{% endfor %}

次に、CSSで次のように記述します。

.name{
      /* you already have this class so create it's style form here */
}
.message{
      /* you already have this class so create it's style form here */
}
label[for='message']{
      /* style for label */
}

この答えが試してみる価値があることを願っています!フォームを含むHTMLファイルをレンダリングするには、ビューを記述しておく必要があります。


ありがとう。しかし、特定のラベルテキストをどのように書くことができますか?
gakeko betsi

2

あなたのフォームクラスを上書きする必要はありません__init__Djangoのセットので、nameidHTMLの属性input秒。次のようなCSSを使用できます。

form input[name='subject'] {
    font-size: xx-large;
}

1
これに追加するには。"subject = forms ..."の場合、id = "id_subject"およびname = "subject"は、これらの属性のDjango規則です。したがって、あなたはまた、{...} #id_subjectを行うことができるはず
solartic

@solartic:そうです、ありがとう。idDjangoがフォームセット用に作成したフィールドはかなり毛むくじゃらなので、これについては触れませんでした…
tehfink

2

これは本当に見なかった...

https://docs.djangoproject.com/en/1.8/ref/forms/api/#more-granular-output

より詳細な出力

as_p()、as_ul()、およびas_table()メソッドは、遅延開発者のための単なるショートカットであり、フォームオブジェクトを表示できる唯一の方法ではありません。

class BoundField HTMLを表示するか、Formインスタンスの単一フィールドの属性にアクセスするために使用されます。

このオブジェクトのstr()(Python 2のユニコード)メソッドは、このフィールドのHTMLを表示します。

単一のBoundFieldを取得するには、フィールドの名前をキーとして使用して、フォームで辞書検索構文を使用します。

>>> form = ContactForm()
>>> print(form['subject'])
<input id="id_subject" type="text" name="subject" maxlength="100" />

すべてのBoundFieldオブジェクトを取得するには、フォームを繰り返します。

>>> form = ContactForm()
>>> for boundfield in form: print(boundfield)
<input id="id_subject" type="text" name="subject" maxlength="100" />
<input type="text" name="message" id="id_message" />
<input type="email" name="sender" id="id_sender" />
<input type="checkbox" name="cc_myself" id="id_cc_myself" />

フィールド固有の出力は、フォームオブジェクトのauto_id設定に従います。

>>> f = ContactForm(auto_id=False)
>>> print(f['message'])
<input type="text" name="message" />
>>> f = ContactForm(auto_id='id_%s')
>>> print(f['message'])
<input type="text" name="message" id="id_message" />

2

Django用に作成された非常に簡単にインストールできる優れたツールがあり、スタイリングに使用できます。これは、Bootstrap、Materialize、Foundationなどのすべてのフロントエンドフレームワークに使用できます。これは、widget-tweaks Documentationと呼ばれます:Widget Tweaks

  1. Djangoの汎用ビューで使用できます
  2. または独自のフォームで:

djangoインポートフォームから

class ContactForm(forms.Form):
    subject = forms.CharField(max_length=100)
    email = forms.EmailField(required=False)
    message = forms.CharField(widget=forms.Textarea)

デフォルトを使用する代わりに:

{{ form.as_p }} or {{ form.as_ul }}

render_field属性を使用して独自の方法で編集できます。これにより、次の例のように、よりHTML風のスタイルを設定できます。

template.html

{% load widget_tweaks %}

<div class="container">
   <div class="col-md-4">
      {% render_field form.subject class+="form-control myCSSclass" placeholder="Enter your subject here" %}
   </div>
   <div class="col-md-4">
      {% render_field form.email type="email" class+="myCSSclassX myCSSclass2" %}
   </div>
   <div class="col-md-4">
      {% render_field form.message class+="myCSSclass" rows="4" cols="6" placeholder=form.message.label %}
   </div>
</div>

このライブラリは、バックエンドからフロントエンドを十分に分離する機会を提供します


1

Django 1.10では(おそらく以前にも)、次のようにしてそれを行うことができます。

モデル:

class Todo(models.Model):
    todo_name = models.CharField(max_length=200)
    todo_description = models.CharField(max_length=200, default="")
    todo_created = models.DateTimeField('date created')
    todo_completed = models.BooleanField(default=False)

    def __str__(self):
        return self.todo_name

形:

class TodoUpdateForm(forms.ModelForm):
    class Meta:
        model = Todo
        exclude = ('todo_created','todo_completed')

テンプレート:

<form action="" method="post">{% csrf_token %}
    {{ form.non_field_errors }}
<div class="fieldWrapper">
    {{ form.todo_name.errors }}
    <label for="{{ form.name.id_for_label }}">Name:</label>
    {{ form.todo_name }}
</div>
<div class="fieldWrapper">
    {{ form.todo_description.errors }}
    <label for="{{ form.todo_description.id_for_label }}">Description</label>
    {{ form.todo_description }}
</div>
    <input type="submit" value="Update" />
</form>

0

編集:私が提案していることを行う別の(少し優れた)方法がここで回答されています:Djangoフォーム入力フィールドのスタイル設定

上記のオプションはすべて素晴らしいですが、違いがあるので、このオプションを投入すると思いました。

フォームにカスタムのスタイルやクラスなどが必要な場合は、フォームフィールドと一致するhtml入力をテンプレートに作成できます。たとえば、CharFieldの場合(デフォルトのウィジェットはTextInput)、ブートストラップのようなテキスト入力が必要だとします。あなたはこのようなことをするでしょう:

<input type="text" class="form-control" name="form_field_name_here">

そして、長いフォームフィールドの名前を入れてhtmlの一致したとしてname(ウィジェットは、おそらく同様の入力タイプと一致する必要があります)、attribueをDjangoはあなたが実行したときにそのフィールド上の全ての同じバリデータを実行しますvalidateか、form.is_valid()

ラベル、エラーメッセージ、ヘルプテキストなどのform.field.error.as_text他のスタイルは、好きなようにしてスタイルを設定できるため、あまり回避策を必要としません。実際のフィールドは、いじくり回す必要があるフィールドです。

これが最善の方法なのか、私が推奨する方法なのかはわかりませんが、それは方法であり、誰かにとっては適切かもしれません。

以下は、スタイリングフォームの便利なウォークスルーであり、SOにリストされているほとんどの回答が含まれています(ウィジェットやウィジェットの微調整でattrを使用するなど)。 https://simpleisbetterthancomplex.com/article/2017/08/19/how-to-render-django-form-manually.html


0

ウィジェットインスタンスのスタイル設定

あるウィジェットインスタンスを別のインスタンスに見た目を変えたい場合は、ウィジェットオブジェクトがインスタンス化されてフォームフィールドに割り当てられるときに追加の属性を指定する必要があります(CSSファイルにいくつかのルールを追加することもできます)。

https://docs.djangoproject.com/en/2.2/ref/forms/widgets/

これを行うには、ウィジェットを作成するときにWidget.attrs引数を使用します。

class CommentForm(forms.Form):
    name = forms.CharField(widget=forms.TextInput(attrs={'class': 'special'}))
    url = forms.URLField()
    comment = forms.CharField(widget=forms.TextInput(attrs={'size': '40'}))

フォーム定義でウィジェットを変更することもできます:

class CommentForm(forms.Form):
    name = forms.CharField()
    url = forms.URLField()
    comment = forms.CharField()

    name.widget.attrs.update({'class': 'special'})
    comment.widget.attrs.update(size='40')

または、フィールドがフォームで直接宣言されていない場合(モデルフォームフィールドなど)、Form.fields属性を使用できます。

class CommentForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['name'].widget.attrs.update({'class': 'special'})
        self.fields['comment'].widget.attrs.update(size='40')

Djangoはレンダリングされた出力に追加の属性を含めます。

>>> f = CommentForm(auto_id=False)
>>> f.as_table()
<tr><th>Name:</th><td><input type="text" name="name" class="special" required></td></tr>
<tr><th>Url:</th><td><input type="url" name="url" required></td></tr>
<tr><th>Comment:</th><td><input type="text" name="comment" size="40" required></td></tr>
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.