2009-08-04 16 views
7

La clase más adelante hereda de la widget de Área de texto y características de código javascript que muestra cuántos caracteres más un usuario puede entrar en un área de texto.Django - ¿cómo puedo acceder al campo de formulario desde el interior de un widget personalizado

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 

La parte pertinente del código del formulario es el siguiente:

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

Se puede ver que me pase el argumento max_length dos veces, una para el campo y otro para el widget. Una mejor forma puede ser acceder al campo de formulario desde dentro del widget y obtener su atributo max_length, de modo que el widget no requiera un argumento max_length. ¿Cómo puedo hacer eso?

Respuesta

2

Técnicamente, un widget no tiene que tener una relación directa de nuevo a un campo, por lo que no lo hace.

Mirando el source of CharField, se puede ver que tiene un método widget_attrs que agrega automáticamente el atributo maxlength a TextInput/PasswordInput campos.

le sugiero que utilice un campo personalizado que anula este método y añade un atributo para su encargo Widget.

Además, no estoy seguro de que dejarlo en attrs sea una buena idea de todas formas: el <TextArea> se representará con un argumento max_length no válido. ¿Tal vez deberías estar pop() soltándolo?

+1

usted ha hecho, gracias. – shanyu

12

Aunque no es necesario para resolver su problema, el acceso al campo de formulario o forma puede ser realmente útil a veces. Ver la respuesta completa en another question, pero en resumen, se puede obligar a la forma o campo para el widget manualmente en forma __init__:

buenos puntos
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

Desde el interior de la clase Form, puede acceder a la instancia del Modelo a través de 'self.instance'. Recuerde que la instancia estará en blanco cuando agregue/cree un nuevo objeto. – JCotton

+1

En versiones recientes, se puede acceder a la instancia a través de '' render en value.instance' (self, nombre, valor, attrs = Ninguno) ' – MarZab

Cuestiones relacionadas