Рубрики
Без рубрики

React для внутренних разработчиков (Часть 1)

Узнайте, как внутренние веб-разработчики могут использовать возможности ReactJS.

Автор оригинала: Oyeniyi Abiola.

Репозиторий GitHub для этого сообщения в блоге https://github.com/gbozee/react-for-backend-dev .

React-это интерфейсная веб-библиотека, которая может использоваться для создания богатых интерфейсных или одностраничных приложений (SPA), но это не означает, что ее нельзя использовать вместе с существующей серверной веб-платформой.

Я бы сказал, что это одна из основных сильных сторон React. С его мощью мы можем с легкостью оживить ваши скучные фоновые веб-приложения/сайты.

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

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

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

  1. Мы можем успешно добавить новую форму в набор форм.
  2. Мы можем принудительно выполнять проверки, налагаемые формой, установленной на сервере.

Для начала мы создаем виртуальную среду для размещения нашего веб-приложения. Я использую 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. || Давайте создадим ваше || индексное представление||, в котором будет размещен наш набор форм в || 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
  • \n
  • `

    Приукрашивая вышеприведенный результат, мы получаем следующее:

    
    
    
    
    
    
    
    
    
  • `

    Из выходных данных видно, что сгенерированный HTML содержит много скрытых полей, но нет кнопки/ссылки, которая помогла бы нам создать новую форму в наборе форм. Мы должны использовать информацию в скрытых полях формы с библиотекой JavaScript для реализации функции add .

    Давайте настроим наш вид и HTML и попробуем сделать нашу форму немного лучше с помощью Bootstrap .

    Полный urls.py содержание:

    Полный || 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 :

    Обратите внимание, где я создал папку || templates ||:

    Теперь страница индекса должна отображаться и быть доступна в браузере.

    Содержание index.html

    
    
    
    
        
        
        
        
        
        
        
        Formset with django
        
    
    
        
    {% csrf_token %}
    {{form.as_ul}}

    Здесь мы видим, что я создал 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 .

    Нам нужно отслеживать количество форм, которые мы успешно добавили, чтобы мы могли добавить локальное состояние в наш компонент || 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)=>
    1} removeForm={this.removeForm} /> )}
    )} })

    Итак, наш компонент Form теперь получает больше реквизита. Кнопка display Remove props определяет, отображается ли кнопка удаления в форме или нет. remove From props принимает функцию, которая должна вызываться дочерней формой при нажатии кнопки удалить форму.

    После реализации вышеизложенного и обновления браузера мы сможем добавлять и удалять формы в набор форм. Мы могли бы проверить элементы с помощью инструментов разработки браузера, чтобы убедиться, что поля id и name for в каждой форме имеют индекс формы и соответствуют реализации Django.

    В следующем сообщении в блоге мы рассмотрим обеспечение того, чтобы максимальное количество форм, требуемых сервером, не превышалось, и обеспечение того, чтобы все работало должным образом, когда форма в конечном итоге будет отправлена. Хорошего вам дня!

    Репо GitHub для этого поста размещено по адресу https://github.com/gbozee/react-for-backend-dev .