2012-07-19 46 views
5

Vì vậy, tôi đang sử dụng giao diện người dùng jQuery đến skin the radio buttons nhưng tôi không thể tải Django để biểu mẫu của tôi theo cách mà nó phải được thực hiện.Tùy chỉnh biểu mẫu Django với phụ kiện RadioSelect

tôi cần phải có cấu trúc này:

<table> 
    <tr> 
     <td><label for="notify_new_friends">Notify when new friends join</label></td> 
     <td class="radio"> 
      <input type="radio" name="notify_new_friends" id="notify_new_friends_immediately" value="1" checked="checked"/><label for="notify_new_friends_immediately">Immediately</label> 
      <input type="radio" name="notify_new_friends" id="notify_new_friends_never" value="0"/><label for="notify_new_friends_never">Never</label> 
     </td> 
    </tr> 
</table> 

Vì vậy, để tóm tắt rằng tôi cần các nút radio trong một lớp học (radio), nơi họ có một inputlabel for.

Khi tôi làm cho hình thức trong mẫu của tôi với {{ profile_form.notify_new_friends }} tôi nhận được như sau:

<ul> 
    <li><label for="id_notify_new_friends_0"><input type="radio" id="id_notify_new_friends_0" value="0" name="notify_new_friends" /> Immediately</label></li> 
    <li><label for="id_notify_new_friends_1"><input type="radio" id="id_notify_new_friends_1" value="1" name="notify_new_friends" /> Never</label></li> 
</ul> 

Đó là chính xác những gì tôi muốn trừ danh sách phần. Vì vậy, tôi đã cố gắng lặp trên nó mang đến cho tôi những nhãn định dạng khác nhau:

{% for item in profile_form.notify_new_friends %} 
    {{ item }} 
{% endfor %} 

mà mang lại cho tôi:

<label><input type="radio" name="notify_new_friends" value="0" /> Immediately</label> 
<label><input type="radio" name="notify_new_friends" value="1" /> Never</label> 

Vì vậy, vấn đề ở đây là nó dừng sử dụng label for và bắt đầu sử dụng chỉ label để wrapp nó tất cả với.

Tôi cũng đã thử làm một cái gì đó như thế này, nhưng sau đó labellabel_tag không hiển thị bất kỳ thứ gì.

{{ profile_form.notify_new_friends.0 }} 
{{ profile_form.notify_new_friends.0.label_tag }} 
{{ profile_form.notify_new_friends.0.label }} 

Vì vậy, có ai biết cách tôi có thể hiển thị đúng cách này không !?

FYI, đây là forms.py tôi:

self.fields['notify_new_friends'] = forms.ChoiceField(label='Notify when new friends join', widget=forms.RadioSelect, choices=NOTIFICATION_CHOICES) 
+0

https://docs.djangoproject.com/en/dev/ref/forms/widgets/#radioselect - bạn đã đọc sách này chưa? –

+0

@ AlexanderA.Sosnovskiy có, nhưng tôi đã bỏ lỡ 'choice_label' để lấy tiêu đề nhãn, nhưng tiếc là làm' {{radio.tag}} 'không cung cấp cho tôi ID và do đó tôi không thể thực hiện' label for' mà tôi cần phải làm. – olofom

+0

id trường được tự động tạo thử, {{field.auto_id}} –

Trả lời

1

Vì nó dường như không phải là một cách tốt để làm điều này tôi đã chọn để sắp xếp lại các mã được tạo sử dụng jQuery.

// First remove the ul and li tags 
$('.radio ul').contents().unwrap(); 
$('.radio li').contents().unwrap(); 
// Then move the input to outside of the label 
$('.radio > label > input').each(function() { 
    $(this).parent().before(this); 
}); 
// Then apply the jQuery UI buttonset 
$(".radio").buttonset(); 

này đã làm cho nó đi từ:

<ul> 
    <li><label for="id_notify_new_friends_0"><input type="radio" id="id_notify_new_friends_0" value="0" name="notify_new_friends" /> Immediately</label></li> 
    <li><label for="id_notify_new_friends_1"><input type="radio" id="id_notify_new_friends_1" value="1" name="notify_new_friends" /> Never</label></li> 
</ul> 

tới:

<input type="radio" id="id_notify_new_friends_0" value="0" name="notify_new_friends" /><label for="id_notify_new_friends_0"> Immediately</label></li> 
<input type="radio" id="id_notify_new_friends_1" value="1" name="notify_new_friends" /><label for="id_notify_new_friends_1"> Never</label></li> 

và phong cách jQuery UI của tôi hoạt động tốt.

+0

Tôi nghĩ rằng nếu có khả năng để làm điều đó mà không có javascript, chúng ta nên tránh js ... Đặc biệt là trên trang tải - hiệu suất tồi tệ hơn, SEO tồi tệ hơn. Nếu chúng ta sử dụng javascript để thao tác, nó phải là thao tác động mà gây ra lý do như tương tác. – kspacja

+0

Tôi không tin rằng một JavaScript đơn giản sắp xếp lại cùng một nội dung trên trang có khả năng ảnh hưởng đến SEO. Điều đó sang một bên, giải pháp này có khả năng hoạt động rất tốt trong quản trị Django, nơi SEO không liên quan và kiểm soát đầu ra HTML sẽ yêu cầu ghi đè nhiều lớp Django như đã đề cập trong câu trả lời của tnajdek. – bpscott

5

Trong mã của tôi, tôi phát hiện ra rằng việc thay đổi các widget từ

forms.RadioSelect 

để

forms.RadioSelect(attrs={'id': 'value'}) 

kỳ diệu làm cho kết quả tag giá trị bao gồm các thuộc tính id với chỉ số của mặt hàng đó nối. Nếu bạn sử dụng

{% for radio in form.foo %} 
    <li> 
     {{ radio }} 
    </li> 
{% endfor %} 

dưới dạng bạn nhận được label quấn quanh một input.Nếu bạn muốn thường hơn input Tiếp theo label, bạn cần phải làm điều này:

{% for radio in form.value %} 
    <li> 
     {{ radio.tag }} 
     <label for="value_{{ forloop.counter0 }}">{{ radio.choice_label }}</label> 
    </li> 
{% endfor %} 
0
Try like this , I got it.. 

from django.forms.widgets import RadioFieldRenderer 
from django.utils.encoding import force_unicode 
from django.utils.safestring import mark_safe 


class RadioCustomRenderer(RadioFieldRenderer): 
    def render(self): 
     return mark_safe(u'%s' % u'\n'.join([u'%s' % force_unicode(w) for w in self])) 

in form 

widgets = { 
      'validity': forms.RadioSelect(renderer=RadioCustomRenderer), 
     } 
1

Thật không may này là phức tạp hơn nó nên được, có vẻ như bạn cần phải ghi đè ít nhất 2 lớp: RadioRendererRadioInput. Sau đây sẽ giúp bạn bắt đầu nhưng bạn có thể cần phải tinh chỉnh nó một chút.

Trước tiên hãy tạo tiện ích đầu vào nút radio tùy chỉnh. Mục đích duy nhất của chúng tôi trọng phương pháp làm là để thoát khỏi cấu trúc gây phiền nhiễu Django thực thi (<label><input /></label>), nơi thay vì chúng ta muốn chúng ta (<label /><input />):

class CustomRadioInput(RadioInput): 
    def render(self, name=None, value=None, attrs=None, choices=()): 
     name = name or self.name 
     value = value or self.value 
     attrs = attrs or self.attrs 
     if 'id' in self.attrs: 
      label_for = ' for="%s_%s"' % (self.attrs['id'], self.index) 
     else: 
      label_for = '' 
      choice_label = conditional_escape(force_unicode(self.choice_label)) 
      return mark_safe(u'%s<label%s>%s</label>' % (self.tag(), label_for, choice_label)) 

Bây giờ chúng ta cần phải ghi đè RadioRenderer để:

  1. Force nó sử dụng đầu vào phụ tùng đài tùy chỉnh của chúng tôi
  2. Di <li> wraping mọi lĩnh vực đơn đầu vào và <ul> gói tất cả các lĩnh vực đầu vào:

cái gì đó dọc những dòng này nên làm:

class RadioCustomRenderer(RadioFieldRenderer): 
    def __iter__(self): 
     for i, choice in enumerate(self.choices): 
      yield CustomRadioInput(self.name, self.value, self.attrs.copy(), choice, i) 

    def __getitem__(self, idx): 
     choice = self.choices[idx] 
     return CustomRadioInput(self.name, self.value, self.attrs.copy(), choice, idx) 

    def render(self): 
     return mark_safe(u'%s' % u'\n'.join([u'%s' % force_unicode(w) for w in self])) 

Cuối cùng hướng dẫn Django để sử dụng tùy chỉnh renderer

notify_new_friends = forms.ChoiceField(label='Notify when new friends join', widget=forms.RadioSelect(renderer=RadioCustomRenderer), choices=NOTIFICATION_CHOICES) 

Hãy nhớ: này bây giờ kết quả đầu ra nút radio cùng với bao gồm <td> do đó bạn cần phải xây dựng một bảng xung quanh nó trong mẫu của bạn, một cái gì đó dọc theo các dòng này:

<table> 
    <tr> 
    <td><label for="{{field.auto_id}}">{{field.label}}</label></td> 
    <td>{{ field.errors }} {{field}}</td> 
    </tr> 
</table> 
Các vấn đề liên quan