Как получить формы Django для отображения атрибута html required? - PullRequest
16 голосов
/ 27 сентября 2011

У меня есть это поле формы:

email = forms.EmailField(
  required=True,
  max_length=100,
)

У него есть обязательный атрибут, но в html он не добавляет атрибут html required.На самом деле он даже не использует email в качестве типа поля, он использует text ... хотя, кажется, он получает max_length очень хорошо.

Actual:

<input id="id_email" type="text" name="email" maxlength="100">

Ожидается:

<input id="id_email" type="email" name="email" maxlength="100" required="true">

Как заставить Django использовать правильные атрибуты в HTML-формах?

Ответы [ 6 ]

16 голосов
/ 27 сентября 2011

Элементы формы Django записываются против <input />, как это существует в HTML 4, где type="text" была правильной опцией для адресов электронной почты. Также не было required="true".

Если вам нужны пользовательские атрибуты HTML, вам нужен ключевой аргумент attrs для виджета . Это будет выглядеть примерно так:

email = forms.EmailField(
    max_length=100,
    required=True,
    widget=forms.TextInput(attrs={ 'required': 'true' }),
)

Вы можете ознакомиться с дополнительной документацией о виджетах здесь . Обсуждение attrs находится в нижней части этой страницы.

Что касается type="email", вы можете отправить его в свой attrs словарь, и Django будет разумно переопределять его значение по умолчанию. Если это не тот результат, который вы получаете, тогда ваш путь к подклассу forms.TextInput, а затем передать его в аргумент widget.

8 голосов
/ 13 мая 2015

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

from django.contrib.admin.widgets import AdminFileWidget
from django.forms.widgets import HiddenInput, FileInput


class HTML5RequiredMixin(object):

    def __init__(self, *args, **kwargs):
        super(HTML5RequiredMixin, self).__init__(*args, **kwargs)
        for field in self.fields:
            if (self.fields[field].required and
               type(self.fields[field].widget) not in
                    (AdminFileWidget, HiddenInput, FileInput) and 
               '__prefix__' not in self.fields[field].widget.attrs):

                    self.fields[field].widget.attrs['required'] = 'required'
                    if self.fields[field].label:
                        self.fields[field].label += ' *'

Поэтому, когда мне нужно создать новую форму или модель, я просто использую:

class NewForm(HTML5RequiredMixin, forms.Form):
    ...
6 голосов
/ 27 ноября 2016

Начиная с Django 1.10, он встроен.

Из заметок о выпуске :

Обязательные поля формы теперь имеют обязательный атрибут HTML.Установите новый атрибут Form.use_required_attribute в False, чтобы отключить его.

6 голосов
/ 29 сентября 2011

Виджет Обезьяны - ваш лучший выбор:

from django.forms.widgets import Widget
from django.contrib.admin.widgets import AdminFileWidget
from django.forms import HiddenInput, FileInput

old_build_attrs = Widget.build_attrs

def build_attrs(self, extra_attrs=None, **kwargs):
    attrs = old_build_attrs(self, extra_attrs, **kwargs)

    # if required, and it's not a file widget since those can have files
    # attached without seeming filled-in to the browser, and skip hidden "mock"
    # fileds created for StackedInline and TabbedInline admin stuff
    if (self.is_required
            and type(self) not in (AdminFileWidget, HiddenInput, FileInput)
            and "__prefix__" not in attrs.get("name", "")):
        attrs['required'] = 'required'

    return attrs

Widget.build_attrs = build_attrs
5 голосов
/ 14 июля 2015

Существует также шаблонное решение с использованием фильтра.Я рекомендую django-widget-tweaks:

{% load widget_tweaks %}

{{ form.email|attr:'required:true' }}

Это было легко.

4 голосов
/ 10 июня 2016

Как вы уже поняли, установка обязательного атрибута Field в True предназначена только для проверки бэкэнда, как описано в документации Django .

Что вам действительно нужно, так это добавить обязательный атрибут в Виджет поля:

email.widget.attrs["required"] = "required"

Но если вы действительно хотите написать элегантный, СУХОЙ код, вы должны создать базовый класс формы, который динамически ищет все необходимые поля и изменяет их обязательный атрибут виджета для вас (вы можете называть его как угодно, но «BaseForm» кажется подходящим):

from django.forms import ModelForm

class BaseForm(ModelForm):
    def __init__(self, *args, **kwargs):
        super(BaseForm, self).__init__(*args, **kwargs)
        for bound_field in self:
            if hasattr(bound_field, "field") and bound_field.field.required:
                bound_field.field.widget.attrs["required"] = "required"

И затем все ваши объекты формы спускаются с него:

class UserForm(BaseForm):
    class Meta:
        model = User
        fields = []

    first_name = forms.CharField(required=True)
    last_name = forms.CharField(required=True)
    email = forms.EmailField(required=True, max_length=100)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...