2011-08-05 25 views
12

私はdjango-uniformを使用していて、いくつかの統一された機能を使用しています。私は、フォーム宣言から独立したCSSウィジェットを直接追加する方法を探しています。djangoフォーム宣言でラベルのCSSクラスを設定するには?

今の私の唯一の方法は私の一般的なフォームテンプレートでJavaScriptのビットを追加し、クラスを追加することです

from django import forms 

def _get_cleaner(form, field): 
    def clean_field(): 
     return getattr(form.instance, field, None) 
    return clean_field 

class UniformROMixin(forms.BaseForm): 
    """ 
    UniformROMixin, inherits to turn some fields read only 

     - read_only = list of field names. 
    """ 

    def __init__(self, *args, **kwargs): 
     super(UniformROMixin, self).__init__(*args, **kwargs) 
     if hasattr(self, "read_only"): 
      if self.instance and self.instance.pk: 
       for field in self.read_only: 
        self.fields[field].widget.attrs['readonly'] = True 
        self.fields[field].widget.attrs['class'] += "readOnly" 
        # here I would like to set css class of the label 
        # created from the self.fields[field].label string 
        setattr(self, "clean_" + field, _get_cleaner(self, field)) 

(私の再利用可能な読み取り専用の自家製のmixinスニペット...ここで、ボーナスとして)マニュアル。

素晴らしいアイデアですか?

私は良い答えがある可能性があります。スニペットた
+2

私は、フォームの宣言でCSSクラスを追加する方法を知りませんが、私が使用してきました:http://pypi.python.org/pypi/django-widget-tweaksを使うと、テンプレート・レベルのラベル・タグやフォーム要素などの属性に便利に属性を追加できます。 – Brandon

+0

提案のためのThanx。私の場合、私はdjango-uniformによって完全に行われたテンプレート部分は扱いません。私はまだどのように作品がウィジェットの "レンダリング"メソッドを見て、それをオーバーライドすることができます... – christophe31

答えて

3

from django.utils.html import escape 

def readonly_cssclass_adder(bound_field, label_content, label_attrs): 
    if 'readonly' in bound_field.field.widget.attrs: 
     if 'class' in attrs: 
      label_attrs['class'] += " readOnly" 
     else: 
      label_attrs['class'] = "readOnly" 
    return label_content, label_attrs 


def add_required_label_tag(original_function, tweak_foos=None): 
    if not tweak_foos: 
     return original_function 

    def required_label_tag(self, contents=None, attrs=None): 
     contents = contents or escape(self.label) 
     if attrs is None: 
      attrs = {} 
     for foo in tweak_foos: 
      contents, attrs = foo(self, contents, attrs) 
     return original_function(self, contents, attrs) 
    return required_label_tag 

def decorate_bound_field(): 
    from django.forms.forms import BoundField 
    BoundField.label_tag = add_required_label_tag(BoundField.label_tag, 
              tweak_foos=[readonly_cssclass_adder]) 
:ここ

How to add css class and "*" to required fields's labels

私のニーズへの適応(まだテストしていないが、私は一度に行わ投稿を編集します)

私がまだ聞いているBoundFieldクラスを調整しない方が良いソリューションがあれば。

編集: は、必要なフィールドを処理するdjangoの統一方法にリンクされている可能性がありますが、readonly_cssclass_adderを呼び出さないようです。

編集2:最後に私が選択する他の方法で「上書き」にuni_form/field.htmlだった私は他とeasyer解決策を見つけた、私の読み取り専用ウィジェットが自動的に読み取り専用ctrlHolderに

を回したが、このほかには、今の私のお気に入りの応答がありますBoundField.label_tagを呼び出さないテンプレート。だからここでフィールドの状態を確認した。

<label for="{{ field.auto_id }}"{% if field.field.required %} 
     class="requiredField{% if field.widget.attrs.readonly %} readOnlyLabel{% endif %}" 
     {% else %}{% if field.widget.attrs.readonly %}class="readOnlyLabel"{% endif %}{% endif %}> 
    {{ field.label|safe }}{% if field.field.required %}<span class="asteriskField">*</span>{% endif %} 
</label> 
18

ウィジェットは、それがレンダリングする入力要素の属性を定義することができますdictを取るattrsキーワード引数を持っています。フォームには、Djangoがフォームを表示する方法を変更するために定義できる属性もあります。次の例を参照してください。

class MyForm(forms.Form): 
    error_css_class = 'error' 
    required_css_class = 'required' 
    my_field = forms.CharField(max_length=10, 
           widget=forms.TextInput(attrs={'id': 'my_field', 
                  'class': 'my_class'})) 

これはどのWidgetクラスでも機能します。残念ながら、ちょうど{{ field }}を実行した場合、Djangoがラベルをレンダリングする方法を変更する簡単な方法はありません。幸いなことに、フォームオブジェクトとテンプレートで少し遊ぶ:

<form> 
    {% for field in form %} 
     <label class="my_class" for="{{ field.name }}">{{ field.label }}</label> 
     {{ field }} 
    {% endfor %} 
    <button type="submit">Submit</button> 
</form> 

その後、再び、あなたは常にあなたが作業しているオブジェクトに任意の属性を追加することができます。

# In a view... 
form = MyForm() 
form.label_classes = ('class_a', 'class_b',) 
# Or by hijacking ```__init__``` 
class MyForm(forms.Form): 
    def __init__(self, *args, **kwargs): 
     self.my_field = forms.CharField(max_length=10, 
             widget=forms.TextInput(attrs={'id': 'my_field', 
                     'class': 'my_class'})) 
     self.my_field.label_classes = ('class_a', 'class_b',) 
     super(MyForm, self).__init__(*args, **kwargs) 

は、テンプレートをレンダリングあなたの空想に合ったものは何でも

<form> 
    {% for field in form %} 
     <label class="{% for class in field.label_classes %}{{ class }} {% endfor %}" 
       for="{{ field.name }}">{{ field.label }}</label> 
     {{ field }} 
    {% endfor %} 
    <button type="submit">Submit</button> 
</form> 

:文脈で、あなたが行うことができますテンプレート内のフォームを持ちます。

+0

優れたソリューション!それらを使用しようとしている人のための最初の行は '{field%in form.myfield%} 'でなければなりません。 – WayBehind

+0

' Field'オブジェクトは反復不可能です – xj9

+0

@ xj9:これはModeFormではどうなりますか? self.fields [field]に属性を追加すると、self.fieldのようにアクセスするとエラーがスローされますが、表示されません。 – Stefan

0

ManyToManyフィールドおよびブートストラップで使用される@ xj9ソリューションに基づいて、わずかにカスタマイズされたオプション.checkbox-inline.radio-inlineのラジオボタンでも同じ動作をします。

のフォーム。PY

class MyForm(forms.ModelForm): 
    def __init__(self, *args, **kwargs): 
     super(MyForm, self).__init__(*args, **kwargs) 

self.fields['m2mfield'] = forms.ModelMultipleChoiceField(
           queryset=Model.objects.all().order_by('name'), 
           required=True, 
           widget=forms.CheckboxSelectMultiple()) 

template.html

<div class="col-sm-9"> 
{% for field in form.m2mfield %} 
    <label class="checkbox-inline" for="{{ field.name }}">{{ field.label }}</label> 
    {{ field }} 
{% endfor %} 
</div> 
関連する問題