2011-08-05 6 views
12

django-uniform을 사용하고 통일 된 기능을 사용하기 위해 양식 선언에서 직접 CSS 클래스를 추가하는 방법을 찾고 있습니다 (독립형 위젯의 경우).장고 양식 선언에서 레이블의 CSS 클래스를 설정하는 방법?

내 일반적인 양식 서식 파일에 자바 스크립트의 비트를 추가하고 클래스를 추가하는 것입니다 지금은

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)) 

내 유일한 방법은 (여기에 보너스, 내 재사용 가능한 읽기 전용 집에서 만든 믹스 인 조각 ...로) 수동.

브릴리언트 아이디어?

내가 좋은 해답이 될 수도 조각 발견
+2

내가 양식 선언에 CSS 클래스를 추가하는 방법을 알고하지 않습니다,하지만 난 사용했습니다 : http://pypi.python.org/pypi/django-widget-tweaks를 사용하면 레이블 태그 및 양식 요소와 같은 속성을 템플릿 수준에서 편리하게 추가 할 수 있습니다. – Brandon

+0

고맙습니다. 제 경우에는 장고 제복에 의해 완전히 완성 된 템플릿 부분을 다루지 않습니다. 나는 여전히 위젯의 "렌더링"메소드가 어떻게 작동 하는지를 볼 수 있으며,이 메소드를 오버라이드한다. – 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 uniform way와 연결될 수 있지만 readonly_cssclass_adder을 호출하지 않는 것으로 보입니다.

편집 : 2 :하지만 내가 다른과 easyer 해결책을 발견, 내 readOnly 인 위젯은 자동으로이 또한 지금은 내가 가장 좋아하는 반응이다 readOnly 인 ctrlHolder에게

를 돌렸다 내가 마지막에 선택하는 다른 방법이었다에 "무시"를 uni_form/field.html 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 키워드 인수가 있습니다. 양식에는 장고가 양식을 표시하는 방법을 변경하기 위해 정의 할 수있는 몇 가지 속성이 있습니다. 다음 예를보십시오 :

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 클래스에서 작동합니다. 불행히도 Django가 단지 {{ field }} 일 경우 레이블을 렌더링하는 방법을 변경하는 쉬운 방법은 없습니다. 템플릿을 렌더링

# 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="my_class" for="{{ field.name }}">{{ field.label }}</label> 
     {{ field }} 
    {% endfor %} 
    <button type="submit">Submit</button> 
</form> 

: 다행히, 당신은 템플릿에 조금 객체 형태로 재생 맥락에서 양식 및 템플릿에 당신은 할 수 있습니다 : 당신의 공상에 맞는 무엇이든

<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.myfield %의 필드에 대해서만}' – WayBehind

+0

'Field' 객체는 반복 가능하지 않습니다. – xj9

+0

@ xj9 :이 방법은 ModeForm에서 어떻게 작동합니까? self.fields [field]에 속성을 추가 할 때 self.field처럼 액세스 할 때 오류가 발생합니다 ... – Stefan

0

ManyToMany 필드 및 부트 스트랩 .checkbox-inline에 사용되는 @ xj9 솔루션을 기반으로하는 약간 사용자 지정된 옵션입니다. .radio-inline으로 라디오 버튼과 동일하게 작동합니다.

형태.평

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>