Создание повторно используемых компонентов в Django

В этом руководстве мы рассмотрим, как создавать серверные компоненты пользовательского интерфейса в Django с помощью django-viewcomponent, который может помочь вам повторно использовать код и поддерживать его в чистоте и ремонтопригодности.

Хотите использовать интерфейсные инструменты и технологии, такие как Stimulus и Tailwind CSS? Ознакомьтесь с нашей серией , состоящей из двух частей, в которой основное внимание уделяется созданию компонентов как на стороне клиента, так и на стороне сервера.

Настройка проекта

Проект Django

Создайте новый каталог проекта вместе с новым проектом Django:

$ mkdir django-component-example && cd django-component-example
$ python3.12 -m venv venv
$ source venv/bin/activate
(venv)$

(venv)$ pip install Django==5.0.3
(venv)$ django-admin startproject django_component_app .
(venv)$ python manage.py migrate
(venv)$ python manage.py runserver

Не стесняйтесь заменить virtualenv и Pip на Poetry или Pipenv. Для получения дополнительной информации ознакомьтесь с Современными средами Python.

Перейдите к http://127.0.0.1:8000/, чтобы просмотреть экран приветствия Django. После завершения работы отключите сервер.

Создайте requirements.txt файл и добавьте Django в качестве зависимости:

Django==5.0.3

Шаблоны

Далее, давайте быстро создадим шаблон.

Начните с добавления нового шаблона URL-адреса в django_component_app/urls.py:

from django.contrib import admin
from django.urls import path
from django.views.generic import TemplateView  # new

urlpatterns = [
    path("", TemplateView.as_view(template_name="index.html")),  # new
    path("admin/", admin.site.urls),
]

Обновите TEMPLATES в django_component_app/settings.py таким образом, Django знает, где найти шаблоны:

TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": ["django_component_app/templates"],  # updated
        "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" в папку "django_component_app". Затем в эту папку добавьте index.html файл:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Bootstrap demo</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css"
          rel="stylesheet"
          integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65"
          crossorigin="anonymous">
</head>
<body>
  <div>
    <button type="button" class="btn btn-primary">Primary</button>
    <button type="button" class="btn btn-secondary">Secondary</button>
    <button type="button" class="btn btn-success">Success</button>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"
          integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4"
          crossorigin="anonymous"></script>
</body>
</html>

Запустите сервер разработки и перейдите к http://127.0.0.1:8000/ снова. Теперь вы должны увидеть три кнопки, которые были стилизованы под Bootstrap.

django-viewcomponent

Как вы, вероятно, уже знаете, Bootstrap предоставляет ряд вспомогательных CSS-классов и атрибутов, которые вы можете использовать для стилизации. Например, для кнопок мы можем изменить:

  1. Раскрасьте с помощью btn-primary и btn-secondary
  2. Размер с btn-lg или btn-sm

Как мы можем сделать цвет и размер динамичными? Вот тут-то и вступает в действие библиотека django-viewcomponent. Мы можем использовать его для создания повторно используемых компонентов для вашего проекта Django.

Добавьте его в requirements.txt файл:

django-viewcomponent==1.0.5

Установка:

(venv)$ pip install -r requirements.txt

Затем добавьте приложение в INSTALLED_APPS в settings.py:

INSTALLED_APPS = [
    ...
    "django_viewcomponent",
]

Измените раздел TEMPLATES в разделе settings.py следующим образом:

TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": ["django_component_app/templates"],
        "APP_DIRS": False,  # updated
        "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",
            ],
            "loaders":[(  # new
                "django.template.loaders.cached.Loader", [
                    "django.template.loaders.filesystem.Loader",
                    "django.template.loaders.app_directories.Loader",
                    "django_viewcomponent.loaders.ComponentLoader",
                ]
            )],
        },
    },
]

После этого мы можем приступить к созданию нашего первого компонента!

Кнопочный компонент

Создать components/button/button.py файл:

from django_viewcomponent import component


@component.register("button")
class ButtonComponent(component.Component):
    template = '<button class="btn {{ self.extra_css }}" type="button">{{ self.content }}</button>'

    size_map = {
        "sm": "btn-sm",
        "lg": "btn-lg",
    }

    variant_map = {
        "primary": "btn-primary",
        "secondary": "btn-secondary",
        "success": "btn-success",
        "danger": "btn-danger",
        "warning": "btn-warning",
        "info": "btn-info",
        "light": "btn-light",
        "dark": "btn-dark",
    }

    def __init__(self, variant="primary", size=None, **kwargs):
        self.variant = variant
        self.extra_css = kwargs.get("extra_css", "")
        self.content = kwargs.get("content", "")

        if self.variant and self.variant in self.variant_map:
            self.extra_css += f" {self.variant_map[self.variant]}"

        # append css class to the extra_css
        if size and size in self.size_map:
            self.extra_css += f" {self.size_map[size]}"

Примечания:

  1. Мы использовали component.register("button") для регистрации компонента как button.
  2. В методе __init__ мы устанавливаем self.extra_css в соответствии с входными данными variant и size.
  3. template - это встроенный HTML-шаблон для компонента button.

Теперь структура ваших файлов и папок должна выглядеть следующим образом:

├── components
│   └── button
│       └── button.py
├── django_component_app
│   ├── __init__.py
│   ├── asgi.py
│   ├── settings.py
│   ├── templates
│   │   └── index.html
│   ├── urls.py
│   └── wsgi.py
├── manage.py
└── requirements.txt

Обновить django_component_app/templates/index.html:

{% load viewcomponent_tags %}

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Bootstrap demo</title>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css"
        rel="stylesheet"
        integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65"
        crossorigin="anonymous">
</head>
<body>
  <div>
    {% component 'button' variant='primary' %}
      Primary
    {% endcomponent %}

    {% component 'button' variant='secondary' %}
      Secondary
    {% endcomponent %}

    {% component 'button' variant='primary' size='sm' %}
      Small button
    {% endcomponent %}

    {% component 'button' variant='primary' size='lg' %}
      Large button
    {% endcomponent %}
  </div>

  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"
          integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4"
          crossorigin="anonymous"></script>
</body>
</html>

Примечания:

  1. Мы поместили {% load viewcomponent_tags %} вверху, чтобы можно было использовать тег {% component %}.
  2. {% component 'button' variant='primary' %} создает компонент button, который мы передали компоненту variant='primary' и дочерним элементам как content.
  3. Выполняется метод __init__ компонента, и template будет использоваться для визуализации компонента.

Перезапустите сервер Django и перейдите к http://127.0.0.1:8000/. Теперь вы должны увидеть:

Button Component

Примечания:

  1. Компонент button помогает нам перенести некоторую логику классов CSS на уровень компонентов. Это помогает сохранить наш шаблон Django чистым и удобным для чтения.
  2. {% component 'button' variant='primary' size='lg' %} делает интерфейс компонента более понятным и упрощает его использование, поэтому вам не нужно так часто обращаться к документации Bootstrap.
  3. Если позже мы захотим переключить наше интерфейсное решение на другой CSS-фреймворк, такой как Tailwind CSS, мы можем просто обновить код компонента, чтобы все было сделано быстро.

Теперь, когда у вас уже есть базовое представление о том, как создать компонент с помощью django-view component, давайте перейдем к более сложному компоненту - модальному.

Давайте сначала взглянем на приведенный ниже код, скопированный из документации Bootstrap :

<!-- Button trigger modal -->
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal">
  Launch demo modal
</button>

<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h1 class="modal-title fs-5" id="exampleModalLabel">Modal title</h1>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        ...
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Save changes</button>
      </div>
    </div>
  </div>
</div>

Я видел, как многие разработчики Django копировали и вставляли приведенный выше код непосредственно в свои шаблоны Django, а затем обновляли код в соответствии со своими потребностями. Хотя это может сработать, это не очень хорошая практика, когда в вашем приложении несколько моделей. Итак, давайте создадим модальный компонент, в который разработчик сможет просто передать заголовок и текстовую часть. Это будет намного понятнее и проще для чтения.

components/modal/modal.py:

from django_viewcomponent import component
from django_viewcomponent.fields import RendersOneField


@component.register("modal")
class ModalComponent(component.Component):
    modal_trigger = RendersOneField()
    modal_body = RendersOneField(required=True)
    modal_footer = RendersOneField(required=True)

    template_name = "modal/modal.html"

    def __init__(self, modal_id, modal_title, **kwargs):
        self.modal_id = modal_id
        self.modal_title = modal_title

Примечания:

  1. Мы создали класс ModalComponent, который расширяет component.Component.
  2. Здесь мы создали три поля слота для компонента, modal_trigger, modal_body, и modal_footer. Синтаксис очень похож на поля модели Django.
  3. modal_trigger является необязательным, поскольку иногда вам может потребоваться активировать модальный режим в JavaScript, поэтому мы не устанавливаем его как требуется.
  4. Мы устанавливаем для template_name значение modal/modal.html, поэтому компонент будет использовать этот шаблон для отображения компонента.
  5. Компонент примет modal_id и modal_title в качестве обязательных аргументов.

Создайте шаблон components/modal/modal.html:

{% if self.modal_trigger.filled %}
  {{ self.modal_trigger.value }}
{% endif %}

<div class="modal fade" id="{{ self.modal_id }}" tabindex="-1" aria-labelledby="{{ self.modal_id }}Label" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h1 class="modal-title fs-5" id="{{ self.modal_id }}Label">{{ self.modal_title }}</h1>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        {{ self.modal_body.value }}
      </div>
      <div class="modal-footer">
        {{ self.modal_footer.value }}
      </div>
    </div>
  </div>
</div>

Примечания:

  1. Мы отображаем modal_trigger только в том случае, если поле "слот" заполнено.
  2. Мы использовали {{ self.modal_body.value }} и {{ self.modal_footer.value }} для отображения содержимого полей slot.

Обновить django_component_app/templates/index.html вот так:

{% load viewcomponent_tags %}

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Bootstrap demo</title>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css"
        rel="stylesheet"
        integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65"
        crossorigin="anonymous">
</head>
<body>
  <div>
    {% with modal_id='example' modal_title='Simple Test'%}
      {% component 'modal' modal_id=modal_id modal_title=modal_title as modal_comp %}
        {% call modal_comp.modal_trigger %}
          <button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#{{ modal_id }}">
            Launch demo modal
          </button>
        {% endcall %}
        {% call modal_comp.modal_body %}
          Modal Content
        {% endcall %}
        {% call modal_comp.modal_footer %}
          <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
          <button type="button" class="btn btn-primary">Save changes</button>
        {% endcall %}
      {% endcomponent %}
    {% endwith %}
  </div>

  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"
          integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4"
          crossorigin="anonymous"></script>
</body>
</html>

Примечания:

  1. Мы устанавливаем modal_id и modal_title в блоке with.
  2. Мы передали значение модальному компоненту.
  3. Мы использовали поля slot для передачи HTML-содержимого компоненту. Это делает код более ясным и легким для понимания.

Modal Component

Затем вы можете обновить модальный компонент, чтобы он поддерживал больше функций. Например:

  1. Используйте size для управления размером модели.
  2. Определите, должна ли модель включать модальный элемент фона.
  3. Определите, можно ли закрыть модель с помощью клавиши ESC.

Вы можете воспользоваться преимуществами объектно-ориентированного программирования и создать легко настраиваемый и повторно используемый модальный компонент.

Если мы продолжим обновлять вышеупомянутый компонент кнопки, то сможем даже написать такой код:

{% with modal_id='example' modal_title='Simple Test'%}
  {% component 'modal' modal_id=modal_id modal_title=modal_title as modal_comp %}
    {% call modal_comp.modal_trigger %}
      {% component 'button' variant='primary' data_bs_toggle="modal" data_bs_target="#{{ modal_id }}" %}Launch demo modal{% endcomponent %}
    {% endcall %}
    {% call modal_comp.modal_body %}
      Modal Content
    {% endcall %}
    {% call modal_comp.modal_footer %}
      {% component 'button' variant='secondary' data_bs_dismiss="modal" %}Close{% endcomponent %}
      {% component 'button' variant='primary' %}Save changes{% endcomponent %}
    {% endcall %}
  {% endcomponent %}
{% endwith %}

Вкладки компонента

Далее давайте создадим компонент вкладок.

components/tabs/tabs.py:

from django_viewcomponent import component
from django_viewcomponent.fields import RendersManyField


@component.register("tabs")
class TabsComponent(component.Component):
    tabs = RendersManyField(required=True)
    panes = RendersManyField(required=True)

    template_name = "tabs/tabs.html"

    def __init__(self, tabs_id, **kwargs):
        self.tabs_id = tabs_id

Здесь мы использовали RendersManyField, потому что мы хотим, чтобы tabs и panes принимали коллекцию элементов.

Добавьте шаблон components/tabs/tabs.html:

<ul class="nav nav-tabs" id="{{ self.tabs_id }}" role="tablist">
  {% for tab in self.tabs.value %}
    <li class="nav-item" role="presentation">
      <button class="nav-link {% if forloop.counter == 1 %}active{% endif %}" id="{{ self.tabs_id }}-tab-{{ forloop.counter }}"
              data-bs-toggle="tab"
              data-bs-target="#{{ self.tabs_id }}-tab-pane-{{ forloop.counter }}"
              type="button"
              role="tab"
              aria-controls="home-tab-pane"
              aria-selected="true">
        {{ tab }}
      </button>
    </li>
  {% endfor %}
</ul>

<div class="tab-content" id="{{ self.tabs_id }}Content">
  {% for pane in self.panes.value %}
    <div class="tab-pane fade {% if forloop.counter == 1 %}show active{% endif %}"
         id="{{ self.tabs_id }}-tab-pane-{{ forloop.counter }}"
         role="tabpanel"
         aria-labelledby="profile-tab"
         tabindex="0">
      {{ pane }}
    </div>
  {% endfor %}
</div>

Мы использовали {% for tab in self.tabs.value %} для перебора коллекции tabs и получения значения.

Затем добавьте следующий HTML-код в django_component_app/templates/index.html:

{% component 'tabs' tabs_id='exampleTab' as tabs_comp %}
  {% call tabs_comp.tabs %}
    Home
  {% endcall %}
  {% call tabs_comp.panes %}
    <div>Home content</div>
  {% endcall %}

  {% call tabs_comp.tabs %}
    Profile
  {% endcall %}
  {% call tabs_comp.panes %}
    <div>Profile content</div>
  {% endcall %}

  {% call tabs_comp.tabs %}
    Contact
  {% endcall %}
  {% call tabs_comp.panes %}
    <div>Contact content</div>
  {% endcall %}
{% endcomponent %}

Мы объединили содержимое вкладок и соответствующих панелей, чтобы сделать код более читабельным.

Tabs Component

Предварительный просмотр компонентов

До сих пор мы редактировали и проверяли наши компоненты, редактируя файл шаблона индекса.

Во время разработки разработчики могут захотеть протестировать компонент в изолированной среде, не затрагивая представления Django или URL-адреса.

К счастью, компонент django-view предоставляет режим предварительного просмотра, позволяющий нам создавать и просматривать компонент в изолированной среде.

Давайте посмотрим, как это работает.

Добавьте в файл настроек следующее:

VIEW_COMPONENTS = {
    "preview_base": ["previews"],
    "show_previews": DEBUG,
}

Примечания:

  1. preview_base это базовый путь для ваших предварительных просмотров.
  2. show_previews это логическое значение, которое используется для управления тем, показывать ли предварительный просмотр или нет. Здесь мы задаем ему то же значение DEBUG. Таким образом, предварительные просмотры будут показаны только в среде разработки.

Обновить django_component_app/urls.py:

from django.contrib import admin
from django.urls import path, include  # updated
from django.views.generic import TemplateView

urlpatterns = [
    path("", TemplateView.as_view(template_name="index.html")),
    path("previews/", include("django_viewcomponent.urls")),  # new
    path("admin/", admin.site.urls),
]

Создайте новый шаблон с именем django_component_app/templates/django_viewcomponent/preview.html:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1.28.0/themes/prism.min.css">
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css"
        rel="stylesheet"
        integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65"
        crossorigin="anonymous">
</head>
<body>
  <div>
    {{ preview_html }}
  </div>

  <div class="view-component-source-example">
    <h2>Source:</h2>
    <pre><code class="language-python">{{ preview_source }}</code></pre>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/prismjs@1.28.0/prism.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/prismjs@1.28.0/components/prism-python.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"
          integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4"
          crossorigin="anonymous"></script>
</body>
</html>

Примечания:

  1. Этот файл шаблона будет использоваться для визуализации предварительного просмотра компонента.
  2. Мы импортировали Bootstrap CSS и JS на страницу, чтобы заставить компонент работать.
  3. Prism используется для выделения кода на странице предварительного просмотра.
  4. preview_html это HTML-код, сгенерированный методами класса preview.

Создать previews/modal_preview.py файл:

from django.template import Context, Template
from django_viewcomponent.preview import ViewComponentPreview


class ModalComponentPreview(ViewComponentPreview):
    def default_modal(self, **kwargs):
        template = Template(
            """
            {% load viewcomponent_tags %}

            {% with modal_id='example' modal_title='Simple Test'%}
              {% component 'modal' modal_id=modal_id modal_title=modal_title as modal_comp %}
                {% call modal_comp.modal_trigger %}
                  <button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#{{ modal_id }}">
                    Launch demo modal
                  </button>
                {% endcall %}
                {% call modal_comp.modal_body %}
                  Modal Content
                {% endcall %}
                {% call modal_comp.modal_footer %}
                  <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
                  <button type="button" class="btn btn-primary">Save changes</button>
                {% endcall %}
              {% endcomponent %}
            {% endwith %}
        """,
        )

        return template.render(Context({}))

Примечания:

  1. Мы создали класс ModalComponentPreview, который наследуется от ViewComponentPreview.
  2. Мы определили общедоступный метод под названием default_modal, который будет использоваться для визуализации предварительного просмотра. default_modal - это также имя предварительного просмотра, и возвращаемое значение равно preview_html в django_component_app/templates/django_viewcomponent/preview.html.
  3. Когда запущен сервер разработки Django, он выполнит поиск файлов по пути preview_base и отобразит предварительный просмотр, вызвав методы - в данном случае, default_modal.
  4. В большинстве случаев вы можете создать несколько методов (несколько предварительных просмотров) для одного компонента, чтобы продемонстрировать, как его использовать.

Перезапустите сервер разработки и перейдите к http://127.0.0.1:8000/previews . Вы должны увидеть предварительный просмотр default_modal. Нажмите на ссылку, чтобы увидеть предварительный просмотр компонента и кода:

Previewing Components

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

С его помощью вы даже можете создать упрощенную версию библиотеки компонентов.

Теперь структура ваших файлов и папок должна выглядеть следующим образом:

├── components
│   ├── button
│   │   └── button.py
│   ├── modal
│   │   ├── modal.html
│   │   └── modal.py
│   └── tabs
│       ├── tabs.html
│       └── tabs.py
├── django_component_app
│   ├── __init__.py
│   ├── asgi.py
│   ├── settings.py
│   ├── templates
│   │   ├── django_viewcomponent
│   │   │   └── preview.html
│   │   └── index.html
│   ├── urls.py
│   └── wsgi.py
├── manage.py
├── previews
│   └── modal_preview.py
└── requirements.txt

Ресурсы внешнего интерфейса

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

  1. Облегченные фреймворки JavaScript: Stimulus, Alpine.js
  2. Реагировать, Vue.js, Стройная
  3. Пользовательские веб-компоненты

И рекомендуется помещать клиентскую логику в файлы JavaScript вместо файлов шаблонов Django, чтобы упростить написание тестов для вашей клиентской логики.

Вы можете разместить ресурсы внешнего интерфейса рядом с серверными компонентами следующим образом:

components
└── modal
    ├── modal.js      # frontend assets
    ├── modal.css     # frontend assets
    ├── modal.html    # backend
    └── modal.py      # backend

Если вы хотите это сделать, пожалуйста, обратите внимание, что файлы Javascript и CSS должны обрабатываться интерфейсными пакетными инструментами, такими как Webpack или Vite. Могут помочь следующие библиотеки:

  1. python-webpack-boilerplate - может помочь вам запустить проект с использованием Django и Webpack за считанные минуты.
  2. django-vite - интеграция голосования в проект Django.

Библиотека компонентов

Возможно ли создать в Django что-то похожее на Storybook, интерфейсную мастерскую для изолированного создания компонентов пользовательского интерфейса и страниц?

Одна из демонстраций, которую вы можете посмотреть, - это https://shakhammer.com/lookbook/. Эта библиотека компонентов разработана мной на основе пакета django-viewcomponent. На вкладке "Параметры" вы найдете интересную информацию о том, что возможно. Пользователь может обновить входные значения, чтобы изменить поведение компонента:

Component Library Demo

Другие компонентные решения

В этом руководстве мы использовали django-viewcomponent в качестве серверного компонента, но есть и другие решения, если вы хотите узнать больше о том, что возможно:

  1. django-components - это очень популярное компонентное решение в сообществе Django.
  2. django-slippers - это еще одно компонентное решение в сообществе Django. Это поощряет разработчиков создавать компоненты в чистых шаблонах Django, поэтому вы можете рассматривать это как улучшенную версию встроенного в Django тега include.
  3. django-pattern-library - это библиотека шаблонов пользовательского интерфейса для Django.

Ресурсы

Следующие статьи написаны разработчиками Ruby on Rails. Я настоятельно рекомендую вам ознакомиться с ними, поскольку это поможет вам лучше понять решение для серверных компонентов. Кроме того, серверные компоненты гораздо более развиты в сообществе Rails.

Заключение

В этом руководстве мы рассмотрели, как создавать серверные компоненты пользовательского интерфейса в Django с помощью библиотеки компонентов django-view.

Библиотека:

  1. Прост в использовании и не нарушит существующий код.
  2. Работает с любыми интерфейсными технологиями, которые вас интересуют.
  3. Может использоваться для создания компонентов в изолированной среде (которую вы можете легко просмотреть).
  4. Может использоваться для поэтапного создания библиотеки компонентов для вашего проекта.
  5. Помогает сделать ваш код более удобным для обслуживания, повторного использования и тестирования.
Вернуться на верх