2009-08-04 12 views
7

Poniższa klasa dziedziczy po widgetie Textarea i zawiera kod javascript, który wyświetla liczbę znaków, które użytkownik może wprowadzić w obszarze tekstowym.django - w jaki sposób uzyskać dostęp do pola formularza z niestandardowego widżetu

class TextAreaWithCharCounter(forms.Textarea): 

    class Media: 
     js = ('js/jquery.charcounter.js',) 

    def render(self, name, value, attrs = None): 
     id = attrs['id'] 
     max_length = self.attrs.get('max_length', 200) 
     output = super(TextAreaWithCharCounter, self).render(name, value, attrs) 
     output += mark_safe(u''' 
         <script type="text/javascript"> 
         $("#%s").charCounter(%d, {classname:"charcounter"}); 
         </script>'''%(id, max_length))   
     return output 

Odpowiedni fragment kodu formularza jest następujący:

class MyForm(forms.Form): 
    foo = forms.CharField(max_length = 200, widget = TextAreaWithCharCounter(attrs={'max_length':200})) 
    ... 

Można zobaczyć, że dwa razy przejść max_length argumentu, jeden w polu i jeden dla widgetu. Lepszym sposobem może być uzyskanie dostępu do pola formularza z widżetu i uzyskanie jego atrybutu max_length, dzięki czemu argument max_length nie będzie wymagany przez widget. Jak mogę to zrobić?

Odpowiedz

2

Z technicznego punktu widzenia widżet nie musi mieć bezpośredniego związku z polem, więc nie robisz tego.

Patrząc na source of CharField widać, że ma widget_attrs metody, która automatycznie dodaje atrybut TextInput/PasswordInput pól maxlength.

Proponuję użyć niestandardowego pola, które zastąpi tę metodę i doda atrybut do niestandardowego widżetu.

Ponadto, nie jestem pewien, czy pozostawienie go w attrs jest dobrym pomysłem, tak czy inaczej - <TextArea> będzie renderowany z niepoprawnym argumentem max_length. Być może powinieneś być pop() go zamiast tego?

+1

dokonaniu dobrych punktów, dzięki. – shanyu

12

Chociaż nie jest to wymagane w celu rozwiązania problemu, dostęp do formularza lub formularza może być czasem przydatny. Zobacz pełną odpowiedź na another question, ale w skrócie, można powiązać formularz lub pole do widgetu ręcznie w formie __init__:

class MyForm(forms.ModelForm): 
    foo = forms.ModelChoiceField(Foo.objects, widget=CustomWidget()) 

    class Meta: 
     model = Bar 

    def __init__(self, *args, **kwargs): 
     super(MyForm, self).__init__(*args, **kwargs) 
     self.fields['foo'].widget.form_instance = self 
+1

Z poziomu klasy Form można uzyskać dostęp do instancji Model za pomocą 'self.instance'. Pamiętaj, że instancja będzie raczej pusta podczas dodawania/tworzenia nowego obiektu. – JCotton

+1

W ostatnich wersjach można uzyskać dostęp do instancji za pośrednictwem 'value.instance' w' render (self, name, value, attrs = None) – MarZab

Powiązane problemy