web-dev-qa-db-ja.com

DjangoフォームのCSSスタイル

次のスタイルを設定したいと思います。

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>

たとえば、外部を提供するためにsubjectemailmessageclassまたはIDを設定するにはどうすればよいですかスタイルシートに?

126
David542

Djangoの<div class = '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のウィジェットと属性を指定する新しい方法が追加されました。

160
shadfc

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

<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は、as_widget()メソッドを持つ BoundField のインスタンスです。

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

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は、CSSクラスMyClassでレンダリングされます。

87
Charlesthk

anyコードをフォームに追加したくない場合(@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>

(また、ソートされていないlistに変更したことに注意してください。)

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

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

すべてのフォームフィールドには既に一意のidがあります。したがって、CSSファイルでid_subjectを参照して、subjectフィールドのスタイルを設定します。 default 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>

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

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

#id_subject, #id_email, #email_message 
{color: red;}
28
John C

このようにすることができます:

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

それがうまくいくことを願っています。

イグナス

11
Ignas Butėnas

this ブログ投稿ごとに、カスタムテンプレートフィルターを使用して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"}}
11
aashanand

このライブラリを使用できます: 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" }}
7
Eamonn Faherty

できるよ:

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

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

5

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

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

よりきめ細かな出力

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

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

Python上のstr()(unicode 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" />
3
BilliAm

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

  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>

このライブラリを使用すると、フロントエンドとバックエンドを十分に分離することができます

2

DjangoはHTML namesのidおよびinput属性を設定するため、フォームクラスの__init__をオーバーライドする必要はないかもしれません。次のようなCSSを使用できます。

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

1つの解決策は、ページの準備ができた後にJavaScriptを使用して必要なCSSクラスを追加することです。たとえば、Djangoフォーム出力をbootstrapクラス(簡潔にするために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>

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

2
Simon Feltman

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>
1
MadPhysicist

次のようなフォームを作成します。

    class MyForm(forms.Form):
         name = forms.CharField(widget=forms.TextInput(attr={'class':'name'}))
         message = forms.CharField(widget=forms.Textarea(attr={'class':'message'}))

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

{% for field in form %}
      <div class="row">
        <label for="{{ field.name}}">{{ field.name }}</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ファイルをレンダリングするビューを作成している必要があります。

0
Aula

編集:私が提案しているもう1つの(わずかに良い)方法は、ここで回答されています: Djangoフォーム入力フィールドスタイリング

上記のオプションはすべて素晴らしいです。異なるので、私はこれを投げると思いました。

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

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

そして、フォームフィールド名がhtml name属性に一致する限り(およびウィジェットはおそらく入力タイプにも一致する必要があります)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
kimbo

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

あるウィジェットインスタンスを別のウィジェットインスタンスと異なるように見せたい場合、ウィジェットオブジェクトがインスタンス化されてフォームフィールドに割り当てられたときに追加の属性を指定する必要があります(そしておそらく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>
0
Freman Zhang