Перейти к содержимому

Как сделать поле необязательным django

  • автор:

Как сделать поле необязательным django

Свойство label позволяет установить текстовую метку, которая отображается рядом с полей. По умолчанию она отображает название самого поля с большой буквы. Например:

from django import forms class UserForm(forms.Form): name = forms.CharField(label="Имя") age = forms.IntegerField(label="Возраст")

Эта форма сформирует следующие поля ввода:

Установка меток для полей ввода в формах django

widget

Параметр widget позволяет задать виджет, который будет использоваться для генерации разметки html:

from django import forms class UserForm(forms.Form): name = forms.CharField(label="Имя") comment = forms.CharField(label="Комментарий", widget=forms.Textarea)

По умолчанию поле CharField использует виджет forms.widgets.TextInput , который создает однострочное текстовое поле. Однако если нам надо создать многострочное текстовое поле, то необходимо воспользоваться виджетом forms.Textarea :

виджеты в формах Django

Значения по умолчанию

С помощью параметра initial можно установить значения по умолчанию.

from django import forms class UserForm(forms.Form): name = forms.CharField(initial="undefined") age = forms.IntegerField(initial=18)

Порядок полей

Поля ввода отображаются на веб-странице в том порядке, в котором они определены в классе формы. С помощью свойства field_order можно переопределить порядок, как в классе формы:

class UserForm(forms.Form): name = forms.CharField() age = forms.IntegerField() field_order = ["age", "name"]

Так и при определении объекта формы в представлении:

def index(request): userform = UserForm(field_order = ["age", "name"]) return render(request, "index.html", )

help_text

Параметр help_text устанавливает подсказку рядом с полем ввода:

from django import forms class UserForm(forms.Form): name = forms.CharField(help_text="Введите свое имя") age = forms.IntegerField(help_text="Введите свой возраст")

Текстовая подсказка help_text в формах Django

Настройка вида формы

С помощью специальных методов можно настроить общее отображение формы:

  • as_table() : отображение в виде таблицы
  • as_ul() : отображение в виде списка
  • as_p() : каждое поле формы отобажается в отдельном параграфе
  • as_div() : каждое поле формы отобажается в отдельном блоке div

Сделать необязательным поле ArrayField в Django модели

Написал класс, хочу добавлять в базу postgeSQL character varying[] для этого нашёл ArrayField . Но форма вечно просит заполнить это поле. При добавлении в null=True в CharField в ArrayField или сам ArrayField ничего не происходит. Как Пофиксить ?

class ApiKey(models.Model): open_key = models.CharField(max_length=128) secret_key = models.CharField(max_length=128) description = models.CharField(max_length=128) restrict_ip = models.BooleanField() ip = ArrayField( models.CharField(max_length=32, blank=True, null=True), size=8 ) valid_to_date = models.DateField() restrict_methods = models.BooleanField() allowed_methods = ArrayField( models.CharField(max_length=32, blank=True, null=True), size=8, ) forbidden_methods = ArrayField( models.CharField(max_length=32, blank=True, null=True), size=8, ) class KeyForm(forms.ModelForm): class Meta: model = ApiKey fields = [ 'description', 'open_key', 'secret_key', 'restrict_ip', 'ip', 'valid_to_date', 'restrict_methods', 'allowed_methods', 'forbidden_methods' ] widgets = < 'description': forms.TextInput(attrs=< 'class': ATTR_CLASS_DEFAULT, 'placeholder': 'description' >), 'open_key': forms.TextInput(attrs=< 'class': ATTR_CLASS_DEFAULT, 'placeholder': 'open_key' >), 'secret_key': forms.TextInput(attrs=< 'class': ATTR_CLASS_DEFAULT, 'placeholder': 'secret_key' >), 'restrict_ip': forms.CheckboxInput(attrs=< >), 'ip': forms.TextInput(attrs=< 'class': ATTR_CLASS_DEFAULT, 'placeholder': 'ip', 'required': False >), 'valid_to_date': forms.DateInput(attrs=< 'class': ATTR_CLASS_DEFAULT, 'placeholder': 'valid_to_date' >), 'restrict_methods': forms.CheckboxInput(attrs=< >), 'allowed_methods': forms.TextInput(attrs=< 'class': ATTR_CLASS_DEFAULT, 'placeholder': 'allowed_methods' >), 'forbidden_methods': forms.TextInput(attrs=< 'class': ATTR_CLASS_DEFAULT, 'placeholder': 'forbidden_methods' >), > labels = < 'description': 'description', 'open_key': 'open_key', 'secret_key': 'secret_key', 'restrict_ip': 'restrict_ip', 'ip': 'ip', 'valid_to_date': 'valid_to_date:', 'restrict_methods': 'restrict_methods', 'allowed_methods': 'allowed_methods', 'forbidden_methods': 'forbidden_methods' >error_messages = < 'description': < 'required': REQUIRED_ERROR, 'max_length': MAX_LENGTH_ERROR.format(255), >, 'open_key': < 'required': REQUIRED_ERROR, 'max_length': MAX_LENGTH_ERROR.format(128), >, 'secret_key': < 'required': REQUIRED_ERROR, 'max_length': MAX_LENGTH_ERROR.format(14), >, 'valid_to_date': < 'required': REQUIRED_ERROR, 'max_length': MAX_LENGTH_ERROR.format(255), >, > help_texts =

Использование форм, не связанных с моделями

На данный момент мы с вами, в целом, познакомились с механизмом маршрутизации, построения моделей, работы с шаблонами и использованием админ-панели. Конечно, это далеко не полный функционал фреймворка Django и мы еще будем возвращаться к этим темам, но на этом занятии мы коснемся новой темы – работы с формами.

Те из вас, кто уже создавал свои сайты, знают, что формы – это один из важнейших элементов большинства сайтов. Например, когда мы выполняем авторизацию или регистрацию, то появляется страница с полями ввода, чекбоксами, кнопками, списками и другими элементами интерфейса:

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

в разделе «Формы», или на официальном англоязычном сайте:

Первое, что нужно знать, это то, что формы в Django можно создавать в связке с моделью какой-либо таблицы БД. Тогда получаем формы, связанные с моделью. Например, когда мы выполняем авторизацию или регистрацию на сайте, то этот процесс, очевидно, связан с данными таблиц, тогда используются формы, связанные с моделями.

Но можно создавать и независимые формы, не привязанные к моделям. Например, когда создается простой поиск или идет отправка письма на электронную почту. Если при этом обращение к БД не требуется, то и форма создается как независимая, самостоятельная.

Сначала мы рассмотрим форму, не связанную с моделью, хотя и сделаем это на примере добавления статей в БД. На следующем занятии модифицируем ее и превратим в форму, связанной с моделью.

В главном меню у нас уже есть пункт для добавления статей:

и функция представления addpage (в файле women/views.py). Немного изменим эту функцию так, чтобы она отображала шаблон addpage.html:

def addpage(request): return render(request, 'women/addpage.html', {'menu': menu, 'title': 'Добавление статьи'})

А сам шаблон addpage.html определим так:

{% extends 'women/base.html' %} {% block content %} h1>{{title}}/h1> p>Содержимое страницы {% endblock %}

Теперь, при обновлении увидим полноценную страницу для добавления нового поста.

Создание класса формы

Все готово для создания формы. В Django существует специальный класс Form, на базе которого удобно создавать формы, не связанные с моделями. Где следует объявлять формы? Обычно, для этого создают в приложении отдельный файл forms.py. Мы так и сделаем (создаем файл women/forms.py). И в этом файле импортируем пакет forms и наши модели (модель Category нам здесь понадобится для формирования списка категорий):

from django import forms from .models import *

Следующий шаг – объявить класс AddPostForm, описывающий форму добавления статьи. Он будет унаследован от базового класса Form и иметь следующий вид:

class AddPostForm(forms.Form): title = forms.CharField(max_length=255) slug = forms.SlugField(max_length=255) content = forms.CharField(widget=forms.Textarea(attrs={'cols': 60, 'rows': 10})) is_published = forms.BooleanField() cat = forms.ModelChoiceField(queryset=Category.objects.all())

Смотрите, мы здесь определяем только те поля, с которыми будет взаимодействовать пользователь. Например, поля модели time_create или time_update нигде не фигурируют, так как заполняются автоматически. Далее, каждый атрибут формы лучше назвать также, как называются поля в таблице women. Впоследствии нам это облегчит написание кода.

В классе формы каждый атрибут – это ссылка на тот или иной экзнмпляр класса из пакета forms. Например, title определен через класс CharField, поле is_published – через BooleanField, а список категорий cat – через класс ModelChoiceField, который формируется из данных таблицы Category.

Почему указаны именно такие классы? И какие классы вообще существуют для формирования полей формы? Полный их список и назначение можно посмотреть на странице русскоязычной документации:

Я советую вам в целом изучить его и знать, как создавать различные типы полей. В частности, класс CharField служит для создания обычного поля ввода, класс BooleanField – для checkbox’а, класс ModelChoiceField – списка с данными из указанной модели.

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

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

def addpage(request): form = AddPostForm() return render(request, 'women/addpage.html', {'menu': menu, 'title': 'Добавление статьи', 'form': form})

Здесь создается экземпляр формы и через переменную form передается шаблону addpage.html. Но это будет работать только при первом отображении формы, когда пользователь еще не заполнил ее поля, то есть, когда форма не ассоциирована с данными. При повторном ее отображении, например, если данные были введены некорректно и нужно показать ошибки ввода, то форма должна сохранять ранее введенную пользователем информацию. Чтобы проделать такой трюк, в функции представления пропишем следующее условие:

def addpage(request): if request.method == 'POST': form = AddPostForm(request.POST) if form.is_valid(): print(form.cleaned_data) else: form = AddPostForm() return render(request, 'women/addpage.html', {'menu': menu, 'title': 'Добавление статьи', 'form': form})

Мы здесь вначале проверяем, если пришел POST-запрос, значит, пользователем были отправлены данные (мы будем передавать их именно POST-запросом). В этом случае наполняем форму принятыми значениями из объекта request.POST и, затем, делаем проверку на корректность заполнения полей (метод is_valid). Если проверка прошла, то в консоли отобразим словарь form.cleaned_data полученных данных от пользователя. Если же проверка на пройдет, то пользователь увидит сообщения об ошибках. Ну, а если форма показывается первый раз (идем по else), то она формируется без параметров и отображается с пустыми полями.

Отображение формы в шаблоне

Осталось отобразить форму в нашем шаблоне. Перейдем в файл addpage.html и пропишем там следующие строчки:

form action="" method="post"> {% csrf_token %} {{ form.as_p }} button type="submit">Добавить/button> /form>

Смотрите, мы самостоятельно прописываем тег для создания формы в HTML-документе, указываем через атрибут action ее обработчик (в данном случае – это тот же адрес страницы, и связанная с ним функция представления addpage). Атрибут method указывает способ передачи информации на сервер (используется POST-запрос). Внутри формы записываем специальный тег csrf_token, который генерирует скрытое поле с уникальным токеном. Это необходимо для защиты от CSRF-атак, когда на каком-либо другом сайте злоумышленник создает по виду неотличимую форму от вашего сайта и пытается заставить пользователя отправить актуальные данные на сервер через подложную форму. Фреймворк Django не станет обрабатывать данные, если отсутствует или не совпадает токен csrf-поля и, тем самым, защищает пользователя от подобных атак.

    или в виде таблицы. Последний вариант, хоть и возможен, но считается устаревшей практикой. Здесь также стоит иметь в виду, что по умолчанию все поля в Django обязательны, если не указано обратное через параметр required=False.

Наконец, последняя строчка – тег создает кнопку типа submit для запуска процесса отправки данных формы на сервер и, в конечном итоге, нашей функции представления addpage.

Если теперь обновить страницу, то увидим все указанные поля формы со списком и кнопкой.

Улучшение внешнего вида формы

Но у нас названия полей отображаются по-английски и нам бы хотелось их изменить. Для этого у каждого класса полей формы есть специальный атрибут label, который и позволяет задавать свои имена, например, так:

class AddPostForm(forms.Form): title = forms.CharField(max_length=255, label="Заголовок") slug = forms.SlugField(max_length=255, label="URL") content = forms.CharField(widget=forms.Textarea(attrs={'cols': 60, 'rows': 10}), label="Контент") is_published = forms.BooleanField(label="Публикация") cat = forms.ModelChoiceField(queryset=Category.objects.all(), label="Категории")

Теперь, все выглядит гораздо приятнее. Давайте для примера сделаем поле content необязательным, а поле is_published с установленной галочкой. Соответственно, в классе CharField пропишем параметр required=False, а в классе BooleanField – параметр initial=True. Еще в классе ModelChoiceField добавим параметр empty_label=»Категория не выбрана», чтобы вместо черточек отображалась по умолчанию в списке эта фраза.

Со всеми возможными параметрами можно ознакомиться в документации, все по той же ссылке:

Способы отображения формы в шаблонах

Давайте теперь посмотрим, что же в действительности представляет собой объект form на примере ручного перебора и отображения всех наших полей. Я сейчас уберу строчку > и вместо нее запишу все поля формы по порядку, друг за другом.

Первое поле title мы сформируем так:

p>label class="form-label" for=">">{{form.title.label}}: /label>{{ form.title }}/p> div class="form-error">{{ form.title.errors }}/div>

Смотрите, мы здесь самостоятельно прописали HTML-теги внутри формы. Сначала идет тег абзаца

, внутри него тег для оформления надписи. У нее указан класс оформления form-label и идентификатор через свойство form.title.id_for_label. Далее, идет само название form.title.label и после тега отображается поле для ввода заголовка form.title. Вот так можно самостоятельно расписать атрибуты объекта form внутри шаблона. Ну а следующая строчка определяет тег

с классом оформления form-error для отображения возможных ошибок при вводе неверных данных. Список ошибок доступен через переменную form.title.errors.

Все, если теперь обновить страницу сайта, то увидим это одно поле в форме. По аналогии можно прописать и все остальные поля:

p>label class="form-label" for=">">{{form.slug.label}}: /label>{{ form.slug }}/p> div class="form-error">{{ form.slug.errors }}/div> p>label class="form-label" for=">">{{form.content.label}}: /label>{{ form.content }}/p> div class="form-error">{{ form.content.errors }}/div> p>label class="form-label" for=">">{{form.is_published.label}}: /label>{{ form.is_published }}/p> div class="form-error">{{ form.is_published.errors }}/div> p>label class="form-label" for=">">{{form.cat.label}}: /label>{{ form.cat }}/p> div class="form-error">{{ form.cat.errors }}/div>

А в самом верху добавим строчку:

div class="form-error">{{ form.non_field_errors }}/div>

для вывода ошибок валидации, не связанных с заполнением того или иного поля.

Это довольно гибкий вариант представления формы и здесь можно очень тонко настроить отображение каждого поля. Однако, объем кода при этом резко возрастает. В большинстве случаев все это можно существенно сократить. Вы, наверное, уже заметили, что все эти строчки, в общем-то, повторяются, а значит, их можно сформировать через цикл, следующим образом:

div class="form-error">{{ form.non_field_errors }}/div> {% for f in form %} p>label class="form-label" for=">">{{f.label}}: /label>{{ f }}/p> div class="form-error">{{ f.errors }}/div> {% endfor %}

Я, думаю, этот ход вполне понятен: мы здесь на каждой итерации имеем объект поля формы и также обращаемся к нужным его атрибутам. Такая запись значительно короче и гибче в плане изменения формы (достаточно поменять класс формы и это автоматом изменит ее вид в шаблоне). Правда, все поля теперь будут иметь одни и те же стили оформления.

Однако, для виджетов стили оформлений можно прописать непосредственно в классе формы. Например, у класса поля ввода title добавить именованный параметр widget:

title = forms.CharField(max_length=255, label="Заголовок", widget=forms.TextInput(attrs={'class': 'form-input'}))

Мы здесь формируем виджет через класс TextInput и указываем у него стиль оформления form-input. При обновлении страницы, видим, что первое поле изменило свой вид. И так можно делать со всеми полями.

Тестирование формы

Если мы попробуем отправить пустую форму на сервер, то браузер укажет, что поле title обязательное. То же самое и для поля URL, напишем что-нибудь латинскими буквами. Выберем категорию и нажмем «Добавить». В результате, в консоли у нас отображается словарь с принятыми данными:

Все это мы можем сохранить в БД и сформировать новый пост. Если же данные в форме окажутся некорректными, например, в поле URL напишем что-то русскими буквами и сделаем отправку. Видим сообщение:

«Значение должно состоять только из латинских букв…»

и в консоли нет отображения данных, то есть, проверка не прошла. Вот так автоматически Django позволяет выполнять проверки на валидность заполненных данных.

Добавление новой записи

Теперь, когда наша форма в целом готова, выполним добавление записи в БД. Для этого после проверки валидности данных, запишем конструкцию:

if form.is_valid(): #print(form.cleaned_data) try: Women.objects.create(**form.cleaned_data) return redirect('home') except: form.add_error(None, 'Ошибка добавления поста')

Мы здесь используем ORM Django для формирования новой записи в таблице women и передаем методу create распакованный словарь полученных данных. Так как метод create может генерировать исключения, то помещаем его вызов в блок try и при успешном выполнении, осуществляется перенаправление на главную страницу. Если же возникли какие-либо ошибки, то попадаем в блок except и формируем общую ошибку для ее отображения в форме.

Давайте, для начала введем корректные данные в форму, тогда после нажатия на кнопку «Добавить» в таблице women появится новая запись с пустым полем для изображения и заполненными всеми остальными полями. Вернемся в форму и попробуем добавить статью с неуникальным слагом. Тогда возникнет исключение и мы увидим сообщение «Ошибка добавления поста». Как видите, все достаточно просто.

Это был пример использования формы не связанной с моделью. В результате, нам пришлось в классе AddPostForm дублировать поля, описанные в модели Women и, кроме того, вручную выполнять сохранение данных в таблицу women. На следующем занятии мы увидим, как все это можно автоматизировать, используя форму в связке с моделью.

Видео по теме

#1. Django — что это такое, порядок установки

Как сделать сделать поле ForeignKey (связь) не обязательным?

как сделать чтобы при добавлении записи можно было как выбирать что-то из связывающей таблицы, так и оставить его пустым если не нужно?

  • Вопрос задан более трёх лет назад
  • 546 просмотров

Комментировать

Решения вопроса 2

Че-то там программирую

sone_field = models.ForeignKey(SomeModel,blank = True, null = True)

Ответ написан более трёх лет назад

zkweb @zkweb Автор вопроса

VladSkliar

Владислав Скляр @VladSkliar

subject = models.ForeignKey(subjects, blank=True, null=True)

Ответ написан более трёх лет назад

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *