Django: как добавить произвольные атрибуты html в поля ввода формы?

102

У меня есть поле ввода, которое отображается с помощью такого шаблона:

<div class="field">
   {{ form.city }}
</div>

Это отображается как:

<div class="field">
    <input id="id_city" type="text" name="city" maxlength="100" />
</div>

Теперь предположим, что я хочу добавить autocomplete="off"атрибут к визуализируемому элементу ввода. Как мне это сделать? Или onclick="xyz()"или class="my-special-css-class"?

Пользователь
источник

Ответы:

126

Проверить эту страницу

city = forms.CharField(widget=forms.TextInput(attrs={'autocomplete':'off'}))
Гален
источник
2
Спасибо. В моем случае я использую ModelForm, поэтому я не определяю явно поля формы (например, class AddressForm (forms.ModelForm): class Meta: model = models.Address) Означает ли это, что я не могу использовать ModelForm или есть что-то особенное? нужно сделать?
Пользователь
1
хорошо, Nevermind, rtfm: docs.djangoproject.com/en/dev/topics/forms/modelforms
Пользователь
1
@InfinitoLoopy внутри формы инициализации , вы можете добавить код для захвата поля и изменения его атрибутов виджетов. Вот некоторые из них, которые я использовал ранее для изменения 3 полей: `` для field_name в ['image', 'image_small', 'image_mobile']: field = self.fields.get (field_name) field.widget.attrs ['data- file '] =' file '`` `
Стюарт Аксон
4
А как насчет атрибутов, которые не принимают аргументов типа «требуется» и «автофокус»?
Вильгельм Клопп
1
Это плохое решение, потому что нет разделения проблем. Атрибуты HTML не следует записывать в коде Python IMO. Раствор Михаила Коробова лучше.
Дэвид Д.
116

Извините за рекламу, но я недавно выпустил приложение ( https://github.com/kmike/django-widget-tweaks ), которое делает такие задачи еще менее болезненными, поэтому дизайнеры могут делать это, не касаясь кода Python:

{% load widget_tweaks %}
...
<div class="field">
   {{ form.city|attr:"autocomplete:off"|add_class:"my_css_class" }}
</div>

или, альтернативно,

{% load widget_tweaks %}
...
<div class="field">
   {% render_field form.city autocomplete="off" class+="my_css_class" %}
</div>
Михаил Коробов
источник
3
Хорошее приложение Майк, именно то, что я искал!
jmagnusson
в документации не говорится о добавлении "widget_tweaks" в установленное приложение в настройках, возможно, стоит добавить это в документацию.
Джеймс Лин
Привет, Джеймс, это не подчеркнуто, но в разделе «Установка» уже есть примечание о добавлении «widget_tweaks» в INSTALLED_APPS.
Михаил Коробов
@MikhailKorobov большое спасибо за это приложение, оно мне очень помогло! Это было как раз то, что я искал. Мне нужна была форма из ModelForm, и я не хотел вручную вставлять эти атрибуты в каждое поле (40 из них), поэтому мне элегантно удалось добиться того же результата за секунды :) Это должен быть принятый ответ!
Ljubisa Livac
Я планировал написать такое приложение. Благодаря экономии моих усилий.
Anuj TBE
32

Если вы используете "ModelForm":

class YourModelForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(YourModelForm, self).__init__(*args, **kwargs)
        self.fields['city'].widget.attrs.update({
            'autocomplete': 'off'
        })
Artificioo
источник
3
Хорошо! Теперь не нужно явно определять все виджеты.
Микаэль Линдлоф
21

Если вы используете ModelForm, помимо возможности использования в __init__качестве @Artificioo, предоставленной в его ответе, widgetsна этот счет есть словарь в Meta:

class AuthorForm(ModelForm):
    class Meta:
        model = Author
        fields = ('name', 'title', 'birth_date')
        widgets = {
            'name': Textarea(attrs={'cols': 80, 'rows': 20}),
        }

Соответствующая документация

Wtower
источник
1
Пытаюсь понять, почему это набрало меньше голосов, чем ответ выше ... иногда я думаю, что разработчики Django / Python просто предпочитают более
сложный
@ trpt4him Использование подхода init полезно для создания Mixin или базового класса, который можно повторно использовать в других формах. Это типично для средних и крупных проектов. Meta.widgets отлично подходит для одной формы. Итак, оба хороших ответа.
Ахорус
3

Я не хотел использовать для этого все приложение. Вместо этого я нашел здесь следующий код https://blog.joeymasip.com/how-to-add-attributes-to-form-widgets-in-django-templates/

# utils.py
from django.template import Library
register = Library()

@register.filter(name='add_attr')
def add_attr(field, css):
    attrs = {}
    definition = css.split(',')

    for d in definition:
        if ':' not in d:
            attrs['class'] = d
        else:
            key, val = d.split(':')
            attrs[key] = val

    return field.as_widget(attrs=attrs)

используйте тег в html файле

{% load utils %}
{{ form.field_1|add_attr:"class:my_class1 my_class2" }}
{{ form.field_2|add_attr:"class:my_class1 my_class2,autocomplete:off" }}
охлр
источник
0

Внешний вид и рендеринг окончательной формыЯ потратил довольно много дней, пытаясь создать повторно используемые шаблоны форм для создания и обновления моделей в формах Django. Обратите внимание, что я использую ModelForm для изменения или создания объекта. Я также использую бутстрап для стилизации моих форм. В прошлом я использовал django_form_tweaks для некоторых форм, но мне потребовалась некоторая настройка без большой зависимости от шаблонов. Поскольку в моем проекте уже есть jQuery, я решил использовать его свойства для стилизации моих форм. Вот код, и он может работать с любой формой.

#forms.py
from django import forms
from user.models import User, UserProfile
from .models import Task, Transaction

class AddTransactionForm(forms.ModelForm):
    class Meta:
       model = Transaction
       exclude = ['ref_number',]
       required_css_class = 'required'

Views.py

@method_decorator(login_required, name='dispatch')
class TransactionView(View):
def get(self, *args, **kwargs):
    transactions = Transaction.objects.all()
    form = AddTransactionForm
    template = 'pages/transaction.html'
    context = {
        'active': 'transaction',
        'transactions': transactions,
        'form': form
    }
    return render(self.request, template, context)

def post(self, *args, **kwargs):
    form = AddTransactionForm(self.request.POST or None)
    if form.is_valid():
        form.save()
        messages.success(self.request, 'New Transaction recorded succesfully')
        return redirect('dashboard:transaction')
    messages.error(self.request, 'Fill the form')
    return redirect('dashboard:transaction')

Примечание по HTML-коду : я использую модальное окно bootstrap4, чтобы избавиться от хлопот по созданию множества представлений. Возможно, лучше использовать общий CreateView или UpdateView. Свяжите Bootstrap и jqQery

 <div class="modal-body">
    <form method="post" class="md-form" action="." enctype="multipart/form-data">
      {% csrf_token %}
      {% for field in form %}
      <div class="row">
        <div class="col-md-12">
          <div class="form-group row">
            <label for="" class="col-sm-4 col-form-label {% if field.field.required %}
            required font-weight-bolder text-danger{%endif %}">{{field.label}}</label>
            <div class="col-sm-8">
              {{field}}
            </div>

          </div>
        </div>
      </div>

      {% endfor %}

      <input type="submit" value="Add Transaction" class="btn btn-primary">
    </form>
  </div>

Код Javascript не забудьте загрузить это в $(document).ready(function() { /* ... */});функцию.

var $list = $("#django_form :input[type='text']");
$list.each(function () {
    $(this).addClass('form-control')
  });
  var $select = $("#django_form select");
  $select.each(function () {
    $(this).addClass('custom-select w-90')
  });
  var $list = $("#django_form :input[type='number']");
  $list.each(function () {
    $(this).addClass('form-control')
  });
  var $list = $("form :input[type='text']");
  $list.each(function () {
    $(this).addClass('form-control')
  });
  var $select = $("form select");
  $select.each(function () {
    $(this).addClass('custom-select w-90')
  });
  var $list = $("form :input[type='number']");
  $list.each(function () {
    $(this).addClass('form-control')
  });
Фахрер Фейтон
источник