フォームがあると仮定する
class SampleClass(forms.Form):
name = forms.CharField(max_length=30)
age = forms.IntegerField()
Django_hacker = forms.BooleanField(required=False)
レンダリングされたページのクラスに基づいてjQueryを使用できるように、各フィールドにcssクラスを定義する方法はありますか?
フォームを手動で作成する必要がないことを望んでいました。
私自身の質問に答えました。 ため息
http://docs.djangoproject.com/en/dev/ref/forms/widgets/#Django.forms.Widget.attrs
ウィジェットのコンストラクターに渡されることに気づきませんでした。
pythonコードの変更を必要とせず、デザイナーと1回限りのプレゼンテーションの変更に適した別のソリューション: Django-widget-tweaks 。誰かがそれを役に立つと思うことを願っています。
次に、クラスのフィールドを宣言した後にウィジェットにクラス定義を追加する別のソリューションを示します。
def __init__(self, *args, **kwargs):
super(SampleClass, self).__init__(*args, **kwargs)
self.fields['name'].widget.attrs['class'] = 'my_class'
Django-widget-tweaks を使用すると、使いやすく、かなりうまく機能します。
それ以外の場合は、カスタムテンプレートフィルターを使用してこれを実行できます。
この方法でフォームをレンダリングすることを検討してください:
<form action="/contact/" method="post">
{{ form.non_field_errors }}
<div class="fieldWrapper">
{{ form.subject.errors }}
<label for="id_subject">Email subject:</label>
{{ form.subject }}
</div>
</form>
form.subjectは、 BoundField のインスタンスであり、as_widgetメソッドを持ちます。
「my_app/templatetags/myfilters.py」にカスタムフィルター「addcss」を作成できます
from Django import template
register = template.Library()
@register.filter(name='addcss')
def addcss(value, arg):
css_classes = value.field.widget.attrs.get('class', '').split(' ')
if css_classes and arg not in css_classes:
css_classes = '%s %s' % (css_classes, arg)
return value.as_widget(attrs={'class': css_classes})
次に、フィルターを適用します。
{% load myfilters %}
<form action="/contact/" method="post">
{{ form.non_field_errors }}
<div class="fieldWrapper">
{{ form.subject.errors }}
<label for="id_subject">Email subject:</label>
{{ form.subject|addcss:'MyClass' }}
</div>
</form>
form.subjectsは、「MyClass」cssクラスでレンダリングされます。
この助けを願っています。
EDIT 1
dimyG の回答に従ってフィルターを更新する
Django-widget-Tweakリンクを追加
EDIT 2
Docs.djangoproject.comで示されているメソッドを展開します。
class MyForm(forms.Form):
comment = forms.CharField(
widget=forms.TextInput(attrs={'size':'40'}))
すべてのフィールドのネイティブウィジェットタイプを知る必要があるのは面倒だと思い、フォームフィールドにクラス名を置くためだけにデフォルトをオーバーライドするのは面白いと思いました。これは私のために働くようです:
class MyForm(forms.Form):
#This instantiates the field w/ the default widget
comment = forms.CharField()
#We only override the part we care about
comment.widget.attrs['size'] = '40'
これは私には少しきれいに見えます。
フォームのすべてのフィールドに特定のクラスを継承させる場合は、forms.ModelForm
から継承する親クラスを定義し、それから継承するだけです。
class BaseForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(BaseForm, self).__init__(*args, **kwargs)
for field_name, field in self.fields.items():
field.widget.attrs['class'] = 'someClass'
class WhateverForm(BaseForm):
class Meta:
model = SomeModel
これにより、コードの複製を追加せずに、アプリケーションのすべてのフォームのすべてのフィールドに'form-control'
クラスを自動的に追加できました。
ビューを変更する簡単な方法を次に示します。テンプレートに渡す直前にビューに追加します。
form = MyForm(instance = instance.obj)
form.fields['email'].widget.attrs = {'class':'here_class_name'}
次のようにクラスをフォームに追加するだけです。
class UserLoginForm(forms.Form):
username = forms.CharField(widget=forms.TextInput(
attrs={
'class':'form-control',
'placeholder':'Username'
}
))
password = forms.CharField(widget=forms.PasswordInput(
attrs={
'class':'form-control',
'placeholder':'Password'
}
))
すべてのフィールドに同じクラスを与える上記のバリエーションがあります(例:jquery Nice rounded corners)。
# Simple way to assign css class to every field
def __init__(self, *args, **kwargs):
super(TranslatedPageForm, self).__init__(*args, **kwargs)
for myField in self.fields:
self.fields[myField].widget.attrs['class'] = 'ui-state-default ui-corner-all'
これを試すことができます。
class SampleClass(forms.Form):
name = forms.CharField(max_length=30)
name.widget.attrs.update({'class': 'your-class'})
...
詳細については、以下を参照してください。 Django Widgets
テンプレートのフォームのフィールドにクラスを追加したい場合(view.pyまたはform.pyにはない)ビューをオーバーライドせずにサードパーティのアプリを変更する場合は、Charlesthkanswer で説明されているテンプレートフィルタが非常に便利です。しかし、この回答では、テンプレートフィルターは、フィールドが持つ可能性のある既存のクラスをオーバーライドします。
これを編集として追加しようとしましたが、新しい回答として書くことをお勧めしました。
そのため、フィールドの既存のクラスを尊重するテンプレートタグを次に示します。
from Django import template
register = template.Library()
@register.filter(name='addclass')
def addclass(field, given_class):
existing_classes = field.field.widget.attrs.get('class', None)
if existing_classes:
if existing_classes.find(given_class) == -1:
# if the given class doesn't exist in the existing classes
classes = existing_classes + ' ' + given_class
else:
classes = existing_classes
else:
classes = given_class
return field.as_widget(attrs={"class": classes})
結局のところ、これはフォームコンストラクター(init function)で、またはフォームクラスが開始された後に行うことができます。これは、独自のフォームを作成しておらず、そのフォームが他の場所から来ている場合に必要になることがあります-
def some_view(request):
add_css_to_fields = ['list','of','fields']
if request.method == 'POST':
form = SomeForm(request.POST)
if form.is_valid():
return HttpResponseRedirect('/thanks/')
else:
form = SomeForm()
for key in form.fields.keys():
if key in add_css_to_fields:
field = form.fields[key]
css_addition = 'css_addition '
css = field.widget.attrs.get('class', '')
field.widget.attrs['class'] = css_addition + css_classes
return render(request, 'template_name.html', {'form': form})
Django Crispy Forms を使用することもできます。これは、BootstrapやFoundationなどのCSSフレームワークを使用する場合にフォームを定義するのに最適なツールです。また、フォームフィールドのクラスを簡単に指定できます。
フォームクラスは次のようにします。
from Django import forms
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Div, Submit, Field
from crispy_forms.bootstrap import FormActions
class SampleClass(forms.Form):
name = forms.CharField(max_length=30)
age = forms.IntegerField()
Django_hacker = forms.BooleanField(required=False)
helper = FormHelper()
helper.form_class = 'your-form-class'
helper.layout = Layout(
Field('name', css_class='name-class'),
Field('age', css_class='age-class'),
Field('Django_hacker', css-class='hacker-class'),
FormActions(
Submit('save_changes', 'Save changes'),
)
)