Отрисовка пользовательского виджета Django

Общая проблема

Допустим, у вас есть определенная модель

class MyModel(models.Model):
    Name = models.CharField(max_length=64)

И сопроводительная форма, которую вы используете для создания

class CreateMyModelForm(forms.ModelForm):
    class Meta:
        model = MyModel
        fields = ['name']

В нормальной ситуации, когда форма отображается в шаблоне я обычно перебираю поля в шаблоне

{%for field in form%}
{{field}}
{%endfor%}

Когда требуется индивидуальный стиль, мне обычно приходится прибегать к размещению моих <div> и <span> в этом цикле и указывать базовый виджет и его attrs в подклассе Meta.

Просматривая документацию Django по этой теме, я понимаю, что это похоже, что мне нужно поиграть с подклассом Media, чтобы все манипуляции происходили в свойстве widgets в Meta, но я просто не могу об этом думать.

Конкретная проблема

Предположим, у меня есть шаблон, в котором TextInput формы должны отображать как в этом шаблоне :

<div class="form-group input-group">
    <span class="input-group-addon">Name</span>
        <input type="text" name="name" class="form-control" placeholder="MyModel Name">
</div>

Как мне создать виджет, чтобы получить тот же результат, используя:

class CreateMyModelForm(forms.ModelForm):
    class Meta:
        model = MyModel
        fields = ['name']
        widgets={'name':MyWidget(addon="Name",placeholder="MyModel Name")}

Я понимаю, что заполнитель - это то, что я могу вставить в attrs инициализацию TextInput, но надстройка (или родительский div, в данном случае) не или, по крайней мере, насколько мне известно

Прошу прощения за длинный вопрос, я просто почувствовал, что мне нужно подробно объяснить эту проблему, потому что это меня уже давно беспокоит ...


person robotHamster    schedule 24.09.2018    source источник
comment
в addon="Name" имя должно входить в диапазон, верно?   -  person Vaibhav Vishal    schedule 24.09.2018
comment
@VaibhavVishal Нет, вы можете найти визуализированную форму здесь, Я пытаюсь что-то сделать для рендеринга полей в разделе Input Groups   -  person robotHamster    schedule 24.09.2018
comment
вам нужно будет создать div и span внутри цикла for вручную, вы можете использовать {{ field.label }} для динамического размещения текста внутри диапазона   -  person Vaibhav Vishal    schedule 24.09.2018
comment
@VaibhavVishal Это то, чем я занимаюсь до сих пор, и мне очень неприятно отслеживать большое количество HTML в корпоративном приложении. Я надеюсь, что у кого-то есть решение получше!   -  person robotHamster    schedule 24.09.2018
comment
есть способы делать то, что вы пытаетесь сделать, но для этого потребуется взломать django, и они только еще больше усложнят ваш код.   -  person Vaibhav Vishal    schedule 24.09.2018


Ответы (1)


Мы можем сделать как показано ниже.

Виджет

from django import forms
from django.template import loader
from django.utils.safestring import mark_safe


class MyWidget(forms.Widget):
    template_name = 'widget_template.html'

    def get_context(self, name, value, attrs=None):
        return {'widget': {
            'name': name,
            'value': value,
        }}

    def render(self, name, value, attrs=None):
        context = self.get_context(name, value, attrs)
        template = loader.get_template(self.template_name).render(context)
        return mark_safe(template)

widget_template.html

<div class="form-group input-group">
    <span class="input-group-addon">Name</span>
        <input type="text" class="form-control" id="mywidget-{{ widget.name }}" name="{{ widget.name }}" />
</div>
person anjaneyulubatta505    schedule 24.09.2018
comment
Обратите внимание, что HTML-код виджетов ДОЛЖЕН иметь атрибут name, иначе администратор Django не сможет прочитать их значения, и они будут просто автоматически исключены из отправки формы. - person Alan Porter; 05.08.2020