django - как получить доступ к полю формы из пользовательского виджета

приведенный ниже класс наследуется от Textarea виджет и функции javascript-код, который отображает, сколько символов больше пользователь может ввести в textarea.

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

соответствующая часть кода формы выглядит следующим образом:

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

вы можете видеть, что я прохожу max_length аргумент дважды, один для поля и один для виджета. Лучшим способом может быть доступ к полю формы изнутри виджета и получение его атрибута max_length, так что аргумент max_length не требует виджет. Как я могу это сделать?

2 ответов


технически виджет не должен иметь прямого отношения к полю, поэтому вы этого не делаете.

смотреть на!--12-->источник CharField, вы можете видеть, что у него есть widget_attrs метод, который автоматически добавляет до TextInput / PasswordInput поля.

Я предлагаю вам использовать настраиваемое поле, которое переопределяет этот метод и добавляет атрибут для вашего настраиваемого виджета.

кроме того, я не уверен, что оставляя его в attrs is в любом случае, хорошая идея -<TextArea> будет отображаться с недопустимым


хотя это не требуется для решения вашей проблемы, доступ к форме или полю формы может быть действительно полезен иногда. См. полный ответ на еще вопрос, но, короче говоря, вы можете привязать форму или поле к виджету вручную в форме __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