次のスタイルを設定したいと思います。
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>
たとえば、外部を提供するためにsubject
、email
、message
にclassまたはIDを設定するにはどうすればよいですかスタイルシートに?
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のウィジェットと属性を指定する新しい方法が追加されました。
これは、カスタムテンプレートフィルターを使用して実行できます。この方法でフォームをレンダリングすることを検討してください。
<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
でレンダリングされます。
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;}
このようにすることができます:
class ContactForm(forms.Form):
subject = forms.CharField(max_length=100)
subject.widget.attrs.update({'id' : 'your_id'})
それがうまくいくことを願っています。
イグナス
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"}}
このライブラリを使用できます: 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" }}
できるよ:
<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}}
は入力タグを出力するだけで、ラベルなど)。
これは本当に見なかった...
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" />
スタイリングに使用するDjango用に作成された非常に簡単で優れたツールがあり、Bootstrap、Materialize、Foundationなどのすべてのフロントエンドフレームワークで使用できます。widget-tweaksDocumentationと呼ばれます: ウィジェットの調整
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>
このライブラリを使用すると、フロントエンドとバックエンドを十分に分離することができます
DjangoはHTML name
sのid
およびinput
属性を設定するため、フォームクラスの__init__
をオーバーライドする必要はないかもしれません。次のようなCSSを使用できます。
form input[name='subject'] {
font-size: xx-large;
}
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さを回避できます。
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>
次のようなフォームを作成します。
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ファイルをレンダリングするビューを作成している必要があります。
編集:私が提案しているもう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
ウィジェットインスタンスのスタイル設定
あるウィジェットインスタンスを別のウィジェットインスタンスと異なるように見せたい場合、ウィジェットオブジェクトがインスタンス化されてフォームフィールドに割り当てられたときに追加の属性を指定する必要があります(そしておそらく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>