РЕПЕТИТОР математика физика информатика
Для школьников и студентов. Подтягивание пробелов. ЦЭ, ЦТ, ОГЭ, ЕГЭ.
Идет набор на ЛЕТО. Жмите для подробностей:)
435 of 818 menu

Поле MultiValueField

Класс MultiValueField применяется для создания полей формы, которые представляют собой комбинацию нескольких подполей. Это поле используется, когда необходимо собрать данные из нескольких полей ввода и обработать их как единое составное значение. Поле принимает список дочерних полей, каждый из которых отвечает за свою часть данных.

Синтаксис

from django import forms class MultiValueField(fields, widget=None, **kwargs)

Основные параметры конструктора:

  • fields - список экземпляров полей, которые будут составлять составное поле
  • widget - виджет для отображения составного поля (по умолчанию MultiWidget)
  • required - определяет, является ли поле обязательным для заполнения (по умолчанию True)

Общее описание

MultiValueField является абстрактным базовым классом, который требует переопределения метода compress. Этот метод отвечает за преобразование списка валидированных значений из дочерних полей в единое составное значение. Поле автоматически обрабатывает валидацию каждого дочернего поля и собирает ошибки в общий список.

Пример

Рассмотрим создание составного поля для ввода телефонного номера, состоящего из кода страны и основного номера:

from django import forms from django.core.exceptions import ValidationError class PhoneNumberField(forms.MultiValueField): def __init__(self, **kwargs): fields = ( forms.CharField(max_length=5, label='Country code'), forms.CharField(max_length=15, label='Phone number'), ) widget = forms.MultiWidget( widgets=( forms.TextInput(attrs={'placeholder': '+7'}), forms.TextInput(attrs={'placeholder': '123-45-67'}), ) ) super().__init__(fields=fields, widget=widget, **kwargs) def compress(self, data_list): if data_list: country_code = data_list[0] phone_number = data_list[1] if not phone_number: raise ValidationError('Phone number is required') return f'{country_code}{phone_number}' return None

Теперь используем это поле в форме:

from django import forms class ContactForm(forms.Form): name = forms.CharField(max_length=100) phone = PhoneNumberField() form = ContactForm(data={ 'name': 'John Doe', 'phone_0': '+7', 'phone_1': '123-45-67', }) if form.is_valid(): res = form.cleaned_data print(res)

Результат выполнения кода:

{'name': 'John Doe', 'phone': '+7123-45-67'}

Пример

Создадим составное поле для ввода диапазона цен с минимальным и максимальным значениями:

from django import forms from django.core.exceptions import ValidationError class PriceRangeField(forms.MultiValueField): def __init__(self, **kwargs): fields = ( forms.DecimalField(max_value=1000000, label='Min price'), forms.DecimalField(max_value=1000000, label='Max price'), ) widget = forms.MultiWidget( widgets=( forms.NumberInput(attrs={'placeholder': 'from'}), forms.NumberInput(attrs={'placeholder': 'to'}), ) ) super().__init__(fields=fields, widget=widget, **kwargs) def compress(self, data_list): if data_list: min_price = data_list[0] max_price = data_list[1] if min_price is not None and max_price is not None: if min_price > max_price: raise ValidationError('Min price cannot be greater than max price') return {'min': min_price, 'max': max_price} return None

Использование поля в форме:

from django import forms class ProductFilterForm(forms.Form): category = forms.ChoiceField(choices=[('electronics', 'Electronics'), ('books', 'Books')]) price_range = PriceRangeField(required=False) form = ProductFilterForm(data={ 'category': 'electronics', 'price_range_0': '100', 'price_range_1': '500', }) if form.is_valid(): res = form.cleaned_data print(res)

Результат выполнения кода:

{'category': 'electronics', 'price_range': {'min': 100, 'max': 500}}

Пример

Рассмотрим обработку ошибок валидации в составном поле для ввода времени с часами и минутами:

from django import forms from django.core.exceptions import ValidationError class TimeField(forms.MultiValueField): def __init__(self, **kwargs): fields = ( forms.IntegerField(min_value=0, max_value=23, label='Hour'), forms.IntegerField(min_value=0, max_value=59, label='Minute'), ) widget = forms.MultiWidget( widgets=( forms.NumberInput(attrs={'placeholder': 'HH'}), forms.NumberInput(attrs={'placeholder': 'MM'}), ) ) super().__init__(fields=fields, widget=widget, **kwargs) def compress(self, data_list): if data_list: hour = data_list[0] minute = data_list[1] if hour is None or minute is None: raise ValidationError('Both hour and minute are required') return f'{hour:02d}:{minute:02d}' return None

Проверим форму с некорректными данными:

from django import forms class ScheduleForm(forms.Form): event_name = forms.CharField(max_length=200) start_time = TimeField() form = ScheduleForm(data={ 'event_name': 'Meeting', 'start_time_0': '25', 'start_time_1': '70', }) if form.is_valid(): res = form.cleaned_data print(res) else: res = form.errors print(res)

Результат выполнения кода:

{'start_time': ['Ensure this value is less than or equal to 23.', 'Ensure this value is less than or equal to 59.']}

Смотрите также

  • поле SplitDateTimeField,
    которое является встроенной реализацией составного поля для даты и времени
  • класс MultiWidget,
    который используется для отображения нескольких виджетов в одном поле
  • поле ComboField,
    которое объединяет несколько валидаторов для одного поля
  • метод clean,
    который используется для валидации нескольких полей формы
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить