Автор оригинала: Oyeniyi Abiola.
Репозиторий GitHub для этого сообщения в блоге https://github.com/gbozee/react-for-backend-dev .
React-это интерфейсная веб-библиотека, которая может использоваться для создания богатых интерфейсных или одностраничных приложений (SPA), но это не означает, что ее нельзя использовать вместе с существующей серверной веб-платформой.
Я бы сказал, что это одна из основных сильных сторон React. С его мощью мы можем с легкостью оживить ваши скучные фоновые веб-приложения/сайты.
В следующих нескольких сообщениях в блоге я буду обсуждать некоторые области, в которых мы можем использовать React для расширения функциональных возможностей, предоставляемых веб-фреймворком Django Python. Это также может быть применено к любому другому веб-фреймворку на стороне сервера.
Наш пример сценария состоит из реализации набора форм в Django. Одна из проблем, которую не решает Django, – это возможность динамического добавления новой формы в набор форм Django в браузере.
Одним из решений этой проблемы является использование jQuery, но, как правило, ему трудно следовать. Это идеальный вариант использования, чтобы попробовать React и посмотреть, как он поможет решить эту проблему. В сценарии, который мы исследуем вместе, мы обеспечим выполнение следующих требований:
- Мы можем успешно добавить новую форму в набор форм.
- Мы можем принудительно выполнять проверки, налагаемые формой, установленной на сервере.
Для начала мы создаем виртуальную среду для размещения нашего веб-приложения. Я использую git bash для Windows, чтобы убедиться, что среда максимально похожа на разные платформы ОС.
$ mkdir react_django $ cd react_django $ virtualenv venv $ source venv/Scripts/activate # in mac and linux source venv/bin/activate $ pip install django $ django-admin startproject formset_in_react $ cd formset_in_react $ python formset_in_react/manage.py runserver
С учетом вышесказанного у нас должен быть функциональный проект Django. Давайте создадим ваше индексное представление
, в котором будет размещен наш набор форм в urls.py
предоставлено Django.
Я собираюсь создать единую форму в Django, на которой будет основан ваш набор форм. Эта форма состоит из двух простых полей: школа
и степень
.
From Django import forms: class EducationForm(forms.Form): school = forms.CharField() course = forms.CharField() EducationFormset = forms.formset_factory(EducationForm,max_num=2)
Набор форм гарантирует, что максимальное количество форм не превышает двух.
Прежде чем мы рискнем войти в React и, давайте посмотрим сгенерированный HTML из набора форм, сгенерированный Django, и подключим все в нашем представлении.
Используя интерактивную оболочку Python, мы получаем следующий HTML-код, сгенерированный из набора форм.
$ python formset_in_react/manage.py shell >>> from formset_in_react.urls import EducationFormset >>> sample_form = EducationFormset() >>> sample_form.as_ul() u'\n
Приукрашивая вышеприведенный результат, мы получаем следующее:
Из выходных данных видно, что сгенерированный HTML содержит много скрытых полей, но нет кнопки/ссылки, которая помогла бы нам создать новую форму в наборе форм. Мы должны использовать информацию в скрытых полях формы с библиотекой JavaScript для реализации функции add
.
Давайте настроим наш вид и HTML и попробуем сделать нашу форму немного лучше с помощью Bootstrap .
Полный urls.py
содержание:
Я буду вносить изменения в конфигурацию Django settings.py
чтобы Django мог найти наши шаблоны
местоположение.
Я буду вносить изменения в конфигурацию Django || settings.py || чтобы Django мог найти наши || шаблоны || местоположение.
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, "templates")], # the change 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ]
Обратите внимание, где я создал папку templates
:
Теперь страница индекса должна отображаться и быть доступна в браузере.
Содержание index.html
Formset with django
Здесь мы видим, что я создал id
перед использованием рендеринга по умолчанию набора форм, предоставленного Django. Я буду захватывать этот id
с помощью React и заменять его измененным набором форм.
Мы должны получить следующее в вашем браузере:
Теперь пришло время настроить React. Я буду использовать простой подход, описанный в моем последнем посте в блоге, чтобы начать работу в React the Easy Way .
Теперь пришло время настроить React. Я буду использовать простой подход, описанный в моем последнем посте в блоге, чтобы начать работу в React the Easy Way .
...
Вспомните исходное содержимое набора форм, о котором мы узнали из терминала. Мы создадим компонент React, который будет содержать это, прежде чем вносить изменения.
// Our source code would go here const React = window.React; const ReactDOM = window.ReactDOM; const createReactClass = window.createReactClass; const Formset = createReactClass({ render(){ return ()} }) ReactDOM.render(,document.getElementById('formset'))
Обновляя нашу страницу, мы все равно должны получить точно такой же вид, но теперь мы взяли под контроль рендеринг формы с помощью React. Наш пользовательский компонент React вводится в элемент form set
id.
Давайте немного упростим наш компонент.
const Form = createReactClass({ render(){ return ()} }) const Formset = createReactClass({ render(){ const management_data = [ {name: "TOTAL", value:1,}, {name: "INITIAL", value: 0}, {name: "MIN_NUM", value: 0}, {name: "MAX_NUM",value: 2} ] return ( {management_data.map((d,index)=> )})} })
Я вытащил фактическую форму в отдельный компонент и избежал дублирования всех скрытых полей. Теперь я могу переместить management_data
из компонента и передать его как props
в Formset
компонент. Это выглядит так:
... const Formset = createReactClass({ render(){ return ({this.props.management_data.map((d,index)=> )})} }) const management_data = [ {name: "TOTAL", value:1,}, {name: "INITIAL", value: 0}, {name: "MIN_NUM", value: 0}, {name: "MAX_NUM",value: 2} ] ReactDOM.render(, document.getElementById('formset') )
Возвращаясь к нашему компоненту Form
, из-за того, что набор форм Django фактически требует данных набора форм, идентификатор каждого поля формы соответствует определенному соглашению, id_form-0-school
где 0
представляет поля в одном экземпляре формы. Мы можем этим воспользоваться.
Нам нужно отслеживать количество форм, которые мы успешно добавили, чтобы мы могли добавить локальное состояние в наш компонент Formset
.
В приведенном выше примере мы создали локальное состояние с именем noOfForms
и установили значение по умолчанию 1. Затем в методе render
компонента formset мы динамически создали массив на основе текущего локального состояния, заполнили его undefined
с помощью метода fill
на прототипе массива, а затем использовали map
для возврата отдельной формы.
Я также добавил кнопку, которая будет отвечать за добавление новой формы на экран. Прямо сейчас он ничего не делает.
В компоненте Form
я получаю индекс формы, переданный из родительского набора Form
, и использую его для создания id
и name
полей в форме, чтобы способ Django не был нарушен.
Давайте завершим реализацию, выполнив действия add
и remove
.
В компоненте Form
я ожидаю props
, который определит, хочу ли я удалить конкретную форму или нет из родительского элемента, а также действие, которое должно произойти при нажатии кнопки remove
.
const Form = createReactClass({ removeForm(e){ e.preventDefault() this.props.removeForm(this.props.index); }, render(){ const school = `form-${this.props.index}-school` const course = `form-${this.props.index}-course` return ()} }){this.props.displayRemoveButton ? : null}
Кнопка Удалить форму
имеет обработчик событий onClick
, который вызывает метод в компоненте с именем removeForm
, который содержит логику вызова переданной функции от родителя, который знает, как удалить форму. Мы предотвращаем любое действие события браузера по умолчанию , вызывая e.preventDefault
, так как мы не хотим, чтобы наша форма была отправлена на сервер по ошибке.
Затем нам нужно будет создать метод для удаления формы из родительского набора форм
.
const Formset = createReactClass({ getInitialState(){ return { noOfForms:1 } }, addNewForm(e){ e.preventDefault() this.setState({noOfForms:this.state.noOfForms+1}) }, removeForm(index){ this.setState({noOfForms: this.state.noOfForms-1}) }, render(){ return ({this.props.management_data.map((d,index)=> )} {Array(this.state.noOfForms).fill().map((form,index)=>)} })
Итак, наш компонент Form
теперь получает больше реквизита. Кнопка display Remove
props определяет, отображается ли кнопка удаления в форме или нет. remove From
props принимает функцию, которая должна вызываться дочерней формой при нажатии кнопки удалить форму.
После реализации вышеизложенного и обновления браузера мы сможем добавлять и удалять формы в набор форм. Мы могли бы проверить элементы с помощью инструментов разработки браузера, чтобы убедиться, что поля id
и name
for в каждой форме имеют индекс формы и соответствуют реализации Django.
В следующем сообщении в блоге мы рассмотрим обеспечение того, чтобы максимальное количество форм, требуемых сервером, не превышалось, и обеспечение того, чтобы все работало должным образом, когда форма в конечном итоге будет отправлена. Хорошего вам дня!
Репо GitHub для этого поста размещено по адресу https://github.com/gbozee/react-for-backend-dev .