Модальный конструктор форм для трясогузки? - PullRequest
0 голосов
/ 05 мая 2020

Привет, я новичок в трясогузке, и до сих пор это было действительно круто. Однако я столкнулся с проблемой при попытке создать модальную версию formbuilder. Я намерен создать кнопку действия в базе. html, которую пользователь может щелкнуть в любой момент времени и ввести модальную всплывающую форму, чтобы оставить отзыв. Есть ли способ добиться этого?

1 Ответ

1 голос
/ 06 мая 2020

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

Как только у вас это будет, вам нужно будет определить, как ваш интерфейс администратора предоставит настройку, которая FormPage будет использоваться в базовом шаблоне для рендеринга модального окна. Хороший вариант - настройки сайта Wagtail .

Отсюда вам нужно получить связанную форму и использовать ее метод get_form() (все страницы, расширяющие AbstractForm или AbstractEmailForm есть это). Если вы хотите понять, как обрабатывается форма, вы можете увидеть здесь код .

Самый простой способ обработать отправку формы - отправить POST в исходную форму, в этом случае нет необходимости быть какой-либо дополнительной обработкой в ​​другом месте. Вы также получаете страницу «Успех», как обычно, без необходимости визуализировать ее внутри модального окна.

Ниже приведен базовый пример кода c, который должен вас начать.

Пример кода. через

1. установить настройки трясогузки

# settings.py

INSTALLED_APPS += [
    'wagtail.contrib.settings',
]

2. Настройте модель настроек

  • Это будет содержать отношение к любому FormPage, вам нужно будет создать страницу формы отдельно.
  • Примечание: вы может захотеть снять флажок «показывать в меню» на странице формы, если вы не хотите, чтобы пользователи могли go переходить к этой форме по ее собственному URL-адресу, а также
  • Документы - https://docs.wagtail.io/en/stable/reference/contrib/settings.html#defining -настройки
  • Не забудьте запустить makemigrations & migrate
from django.db import models
from wagtail.contrib.settings.models import BaseSetting, register_setting
from wagtail.admin.edit_handlers PageChooserPanel

# ... other models & imports

@register_setting
class MyAppSettings(BaseSetting):
    # relationship to a single form page (one per site)
    modal_form_page = models.ForeignKey(
        'wagtailcore.Page',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
        verbose_name='Modal Form'
    )

    panels = [
        # note the kwarg - this will only allow form pages to be selected (replace base with your app)
        PageChooserPanel('modal_form_page', page_type='base.FormPage')
    ]

3. Установите базовую c модальную библиотеку

  • Это зависит от вас, например, если вы используете bootrap, она поставляется с модальной библиотекой
  • В этом примере я использовал https://micromodal.now.sh/#installation
  • Есть много способов сделать это, это самый простой и не требует никаких асинхронных c фоновых вызовов сервера

3a . Добавьте css в папку stati c (например, my-app / static / css / micromodal. css), а затем импортируйте его в центральный заголовок или шаблон макета.

<head>
  <!-- ALL OTHER ITEMS -->
  <!-- Modal CSS -->
  <link href="{% static 'css/micromodal.css' %}" rel="stylesheet" type="text/css">
</head>

3b . Добавьте вызов JS & init в ваш базовый шаблон, лучше всего сделать это как последний элемент перед закрывающим тегом body

<!-- Modal JS -->
<script src="https://unpkg.com/micromodal/dist/micromodal.min.js"></script>
<script>
    document.addEventListener("DOMContentLoaded", function() {
        MicroModal.init();
    });
</script>

4. Настройте тег шаблона

  • Есть несколько способов сделать это, но в основном мы хотим, чтобы в нашем шаблоне base.html был удобный способ размещения модального и модального триггера. template tags Django - отличный способ сделать это.
  • Docs - https://docs.djangoproject.com/en/3.0/howto/custom-template-tags/#inclusion -tags
  • Использование инструкций на странице настроек сайта Wagtail мы можем импортировать нашу модель настроек и получить доступ к соответствующей странице формы, отсюда мы можем сгенерировать объект формы.
  • Приведенный ниже код шаблона является минимальным, вы, вероятно, захотите сделать больше стилей, он предполагает триггер будет просто отображаться вместе с модальным содержимым.
  • Шаблон содержит некоторые базовые c logi c, позволяющие отслеживать страницу, на которой форма была отправлена ​​source-page-id, чтобы мы могли перенаправить пользователя на их исходную страницу и чтение request.session, чтобы показать сообщение об успешном завершении.
# my-app/templatetags/modal_tags.py
from django import template
from models import MyAppSettings

register = template.Library()

# reminder - you will need to restart Django when adding a template tag


@register.inclusion_tag('tags/form_modal.html', takes_context=True)
def form_modal(context):
    request = context['request']  # important - you must have the request in context
    settings = MyAppSettings.for_request(request)
    form_page = settings.modal_form_page

    if not form_page:
        return context

    form_page = form_page.specific

    # this will provide the parts needed to render the form
    # this does NOT handle the submission of the form - that still goes to the form page
    # this does NOT handle anything to do with rendering the 'thank you' message

    context['form_page'] = form_page
    context['form'] = form_page.get_form(page=form_page, user=request.user)

    return context
{% comment %} e.g. my-app/templates/tags/form_modal.html {% endcomment %}
{% load wagtailcore_tags %}

{% if request.session.form_page_success %}
  Thanks for submitting the form!
{% endif %}

{% if form %}

<button data-micromodal-trigger="modal-1">Open {{ form_page.title }} Modal</button>

<div class="modal micromodal-slide" id="modal-1" aria-hidden="true">
  <div class="modal__overlay" tabindex="-1" data-micromodal-close>
    <div class="modal__container" role="dialog" aria-modal="true" aria-labelledby="modal-1-title">
      <header class="modal__header">
        <h2 class="modal__title" id="modal-1-title">
          {{ form_page.title }}
        </h2>
        <button class="modal__close" aria-label="Close modal" data-micromodal-close></button>
      </header>
      <form action="{% pageurl form_page %}" method="POST" role="form">
        <main class="modal__content" id="modal-1-content">
          {% csrf_token %}
          {{ form.as_p }}
          {% if page.pk != form_page.pk %}
          {% comment %} only provide the source page if not on the actual form page {% endcomment %}
          <input name="source-page-id" type="hidden" value="{{ page.pk }}">
          {% endif %}
        </main>
        <footer class="modal__footer">
          <input class="modal__btn modal__btn-primary" type="submit">
          <button class="modal__btn" data-micromodal-close aria-label="Close this dialog window">Close</button>
        </footer>
      </form>
    </div>
  </div>
</div>

{% endif %}

5. Используйте тег шаблона там, где вы хотите, чтобы модальный триггер

  • Теперь вы можете добавить модальный (вместе с его триггером)
  • Важно: чтобы тег шаблона выше имел доступ к запросу через контекст вам может потребоваться добавить это (в зависимости от вашей настройки).
    <!-- Footer -->
    <footer>
        {% form_modal %}
        {% include "includes/footer.html" %}
    </footer>

6. Перенаправление обратно на исходную страницу

  • В качестве последнего шага мы можем перенаправить пользователя обратно на исходную страницу, прочитав source-page-id из request.POST.
  • С этого идентификатора мы можем получить исходный URL-адрес и использовать ярлык Django redirect .
  • Перед перенаправлением мы обновили request.session некоторыми данными, чтобы мы могли показать сообщение об успешном завершении.
  • Это можно сделать, переопределив render_landing_page в FormPage
  • Документы - https://docs.wagtail.io/en/latest/reference/contrib/forms/customisation.html#custom -landing-page-redirect
# models.py

class FormPage(AbstractEmailForm):
    # .. fields etc

    def render_landing_page(self, request, form_submission=None, *args, **kwargs):
        source_page_id = request.POST.get('source-page-id')
        source_page = Page.objects.get(pk=source_page_id)

        if source_page:
            request.session['form_page_success'] = True
            return redirect(source_page.url, permanent=False)

        # if no source_page is set, render default landing page
        return super().render_landing_page(request, form_submission, *args, **kwargs)
...