2011-04-05 2 views
3

위치 모델과 값을 표시하기 위해 양식 쿼리 세트를 사용하는 라디오 버튼 모음으로 "위치"필드를 표시하는 관련 양식이 있습니다. 적은 수의 위치가 있지만 동적이어야합니다. 각 라디오 박스 옵션 옆에 위치 설명을 표시하여 사용자가 위치에 대해 더 많은 정보를 갖도록하고 싶습니다. 이 위치는 동쪽이다 - 모델에서 추가 정보가있는 장고 렌더링 라디오 버튼 옵션

<> 이스트

:

이 라디오 버튼의 목록입니다 척이 내가 그것을 모양을하고 싶은 것입니다. <> 서쪽 - 이것은 서쪽 위치입니다! <> 북한 -이 북쪽 위치를입니다

나는 다음과 같은 모델이 있습니다

class Location(models.Models): 
    location = models.CharField(max_length=50) 
    description = models.TextField(blank=True, null=True) 

과 같은 형태 :

class LocationForm(forms.Form): 
    location = ExtraModelChoiceField(
       widget=RadioSelect(renderer=ExtraHorizRadioRenderer), 
       queryset = models.Locations.objects.filter(active=True)) 

내가 찾을 수 없습니다를 양식을 렌더링하는 좋은 방법으로 각 선택 옵션과 함께 설명을 표시 할 수 있습니다. 나는 많은 오버라이드를했지만, 너무 많은 행운이 없다. (아직하지만 NO LUCK) 해결하기 위해

내 시도는 :

내가 수집 무엇부터

하는의 검색어가 양식 필드에 제공되는 일반적 경우, 장고 양식 로직은 변환 tupals의 선택의 tupal에 그. 각 "subtupal"은 렌더링 될 때 표시되는 ID와 레이블을 포함합니다. 나는 "subtupals"에 세 번째 값을 추가하여 설명을하려고합니다.

라디오 버튼을 수평으로 표시하고 사용자 정의 선택 항목을 전달하기 위해 사용자 정의 렌더러를 정의했습니다.

class ExtraHorizRadioRenderer(forms.RadioSelect.renderer): 
    def render(self): 
     return mark_safe(u'\n'.join([u'%s\n' % w for w in self])) 

    def __iter__(self): 
     for i, choice in enumerate(self.choices): 
      yield ExtraRadioInput(self.name, self.value, 
            self.attrs.copy(), choice, i) 

    def __getitem__(self, idx): 
     choice = self.choices[idx] # Let the IndexError propogate 
     return ExtraRadioInput(self.name, self.value, 
           self.attrs.copy(), choice, idx) 

나는 그래서 내가 라디오 버튼 옆에 표시하는 데 필요한 기술 정보를 추가 할 수 있습니다 장고 RadioInput 클래스를 무시했습니다.

class ExtraRadioInput(forms.widgets.RadioInput): 

    def __init__(self, name, value, attrs, choice, index): 
     self.name, self.value = name, value 
     self.attrs = attrs 
     self.choice_value = force_unicode(choice[0]) 
     self.choice_label = force_unicode(choice[1]) 
     self.choice_description = force_unicode(choice[2]) # <--- MY ADDITION; FAILS 
     self.index = index 

    def __unicode__(self): 
     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'<label%s>%s %s</label>' % (
      label_for, self.tag(), choice_label)) 

    def tag(self): 
     if 'id' in self.attrs: 
      self.attrs['id'] = '%s_%s' % (self.attrs['id'], self.index) 
     final_attrs = dict(self.attrs, type='radio', name=self.name, 
         value=self.choice_value) 
     if self.is_checked(): 
      final_attrs['checked'] = 'checked' 
     return mark_safe(
      u'<input%s /><span class="description">%s</span>' % \ 
      (flatatt(final_attrs),self.choice_description)) # <--- MY ADDTIONS 

또한 수정 된 선택 사항 tupals를 전달하고자하는 다음 두 장고 클래스를 재정의했습니다.

class ExtraModelChoiceIterator(forms.models.ModelChoiceIterator ):  

    def choice(self, obj): 
     if self.field.to_field_name: 
      key = obj.serializable_value(self.field.to_field_name) 
     else: 
      key = obj.pk 

     if obj.description: # <-- MY ADDITIONS 
      description = obj.description 
     else: 
      description = "" 
     return (key, self.field.label_from_instance(obj),description) 


class ExtraModelChoiceField(forms.models.ModelChoiceField): 

    def _get_choices(self): 
     if hasattr(self, '_choices'): 
      return self._choices 
     return ExtraModelChoiceIterator(self) # <-- Uses MY NEW ITERATOR 

위의 방법을 사용하면 3 차원 값을 갖는 투플을 전달할 수없는 것처럼 보입니다. 나는 어떻게 든 내 tupal이 여분의 가치를 가지지 않는다는 것을 가리키는 "범위를 벗어난 튜플 인덱스"실패 (위의 FAILURE를 표시)를 얻는다.

내 논리에 결함이 있거나 더 일반적으로 위젯을 사용하여 선택 목록 옆에 설명을 표시하는 방법이 있습니까?

읽어 주셔서 감사합니다. 모든 의견을 많이 보내 주시면 감사하겠습니다. 조

+1

CSS를 사용해 보셨습니까? 그것은 나에게 훨씬 쉬워 보인다. Python/Django 개발자가 서버 측 코드에서 이와 같은 형식을 지정하는 것에 대해 걱정할 필요가없는 것 같습니다. – Spike

답변

2

내 자신의 질문에 답변 해 드려 죄송합니다.하지만이 방법이 있습니다. 늘 그렇듯이 이전보다 더 단순 해 보입니다. 확장 된 ModelChoiceField에서 label_from_instance 메서드를 재정의하면 모델 객체 인스턴스에 액세스하여 추가 정보를 인쇄 할 수 있습니다.

from django.utils.encoding import smart_unicode, force_unicode 

class ExtraModelChoiceField(forms.models.ModelChoiceField): 

    def label_from_instance(self, obj): 
     return mark_safe(
      "<span>%s</span><span class=\"desc\" id=\"desc_%s\">%s</span>" % (
      mart_unicode(obj), obj.id, smart_unicode(obj.description),)) 


class HorizRadioRenderer(forms.RadioSelect.renderer): 
    # for displaying select options horizontally. 
    # https://wikis.utexas.edu/display/~bm6432/Django-Modifying+RadioSelect+Widget+to+have+horizontal+buttons 
    def render(self): 
     return mark_safe(u'\n'.join([u'%s\n' % w for w in self])) 


class LocationForm(forms.Form): 
    location = ExtraModelChoiceField(widget=forms.RadioSelect(renderer=HorizRadioRenderer), 
     queryset=models.Location.objects.filter(active=True)) 

더 나은 접근 방법을 알고 있다면 나는 그것을보고 기뻐할 것입니다. 그렇지 않으면, 이것은해야 할 것입니다. 읽어 주셔서 감사합니다. 이것이 내가 누군가를 좌절시키지 않기를 바란다.

관련 문제