https://www.accordbox.com/blog/how-build-form-page-wagtail/

 

Wagtail에서 Form을 적용하는 방법에 대해서 알아보자. 

Wagtail에서는 이미 Form 생성 툴을 제공한다. 

 

1. Form 페이지 생성

forms/models.py

from wagtail.contrib.forms.models import AbstractEmailForm, AbstractFormField

class FormField(AbstractFormField):
    page = ParentalKey('FormPage', related_name='custom_form_fields')


class FormPage(AbstractEmailForm):
    thank_you_text = RichTextField(blank=True)

    content_panels = AbstractEmailForm.content_panels + [
        InlinePanel('custom_form_fields', label="Form fields"),
        FieldPanel('thank_you_text', classname="full"),
        MultiFieldPanel([
            FieldRowPanel([
                FieldPanel('from_address', classname="col6"),
                FieldPanel('to_address', classname="col6"),
            ]),
            FieldPanel('subject'),
        ], "Email Notification Config"),
    ]

    def get_form_fields(self):
        return self.custom_form_fields.all()

AbstractFormField는 wagtail에서 제공하는 Form Builder이다. 사용자가 Form을 전송하고 나서 보여지는 메세지을 thank_you_text 필드에 저장한다. from_address하고 to_address는 사용자가 form을 작성하고 submit을 눌렀을 때, to_address에 있는 메일 주소로 메일을 보내게 할 수 있다. 나는 현재 만드는 Form에서는 쓰지 않지만 사용할 일이 있을 수도 있으니 일단 적어놨다. 

 

settings/dev.py에 다음을 추가하자 (이미 기본적으로 추가되어 있을 것이다.)

EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

 

Form Type에는 여러가지 Form을 선택할 수 있고 Form들을 조합해서 새로운 Form 양식을 만들어 낼 수 있다. 

 

2. 템플릿 작성

 

템플릿에서 표현하기 위해 다음 모듈을 설치해주자.

pip install django-widget-tweaks

django-widget-tweaks는 파이썬 수준의 폼 정의가 아닌 템플릿의 폼 필드 렌더링을 조정한다. CSS 클래스 및 HTML 속성 변경을 지원한다. 즉 우리가 Form을 원하는대로 Custom 할 수 있게 해준다.

 

user_management/form_page.html

{% extends "base.html" %}
{% load static wagtailcore_tags widget_tweaks %}

{% block content %}

<h1>Contact</h1>
<br>

<form action="{% pageurl page %}" method="POST">
    {% csrf_token %}

    {% if form.non_field_errors %}
    <div class="alert alert-danger" role="alert">
        {% for error in form.non_field_errors %}
            {{ error }}
        {% endfor %}
    </div>
    {% endif %}

    {% for field in form.visible_fields %}
        <div class="form-group">
            {{ field.label_tag }}
            {% render_field field class+="form-control" %}
        </div>
    {% endfor %}

    <button type="submit" class="btn btn-primary" >Submit</button>
</form>

{% endblock %}

Form Page 템플릿이다. 여기서 우리가 Admin Page에서 만든 Form Page양식이 보여진다. 그리고 submit을 하면 정상적으로 제출되었다고 알려줄 수 있게 landing page를 추가하자. 

 

user_management.py/form_page_landing.html

{% extends "blog/base.html" %}

{% load static wagtailcore_tags  wagtailimages_tags el_pagination_tags menu_tags %}

{% block content %}

<h2>{{ page.thank_you_text | richtext }}</h2>

{% endblock %}

모델에서 작성한 tank_you_text 필드가 보여질 것이다. Form Page에서 정상적으로 제출된 Form들은 Wagtail Admin Page에 Forms에 저장되어 있을 것이다.

 

추가) Form Custom

 

기본 Form 작성법을 알았으니 추가적으로 Custom 하는 방법에 대해서 알아보자

https://docs.wagtail.io/en/stable/reference/contrib/forms/customisation.html

 

1. custom field 추가 

forms/models.py

from django import forms
from django.db import models
from modelcluster.fields import ParentalKey
from wagtail.contrib.forms.forms import FormBuilder
from wagtail.contrib.forms.models import (
  AbstractEmailForm, AbstractFormField, FORM_FIELD_CHOICES)


class FormField(AbstractFormField):
    # extend the built in field type choices
    # our field type key will be 'ipaddress'
    CHOICES = FORM_FIELD_CHOICES + (('ipaddress', 'IP Address'),)

    page = ParentalKey('FormPage', related_name='form_fields')
    # override the field_type field with extended choices
    field_type = models.CharField(
        verbose_name='field type',
        max_length=16,
        # use the choices tuple defined above
        choices=CHOICES
    )


class CustomFormBuilder(FormBuilder):
    # create a function that returns an instanced Django form field
    # function name must match create_<field_type_key>_field
    def create_ipaddress_field(self, field, options):
        # return `forms.GenericIPAddressField(**options)` not `forms.SlugField`
        # returns created a form field with the options passed in
        return forms.GenericIPAddressField(**options)


class FormPage(AbstractEmailForm):
    # intro, thank_you_text, edit_handlers, etc...

    # use custom form builder defined above
    form_builder = CustomFormBuilder

FormField정의하고 Form type 리스트에 추가하고 CustomFormBuilder에 추가해주면 된다. 

field type에 리스트로 저장될 새로운 field이름은 튜플형태로 작성해주면 된다. 

('ipaddress', 'IP Address') 에서 앞쪽이 리스트에 표시될 이름이다.

 

2. render page 수정

기본적으로 form을 제출하고 나면 form_page_landing.html로 redirect된다. 특정 page로 가고 싶을때는 다음과 같이 작성하면된다. 

 

forms/models.py

    def render_landing_page(self, request, form_submission=None, *args, **kwargs):
        if self.thank_you_page:
            url = self.thank_you_page.url
            # if a form_submission instance is available, append the id to URL
            # when previewing landing page, there will not be a form_submission instance
            if form_submission:
              url += '?id=%s' % form_submission.id
            return redirect(url, permanent=False)
        # if no thank_you_page is set, render default landing page
        return super().render_landing_page(request, form_submission, *args, **kwargs)

FormPage에 추가해주면 된다. 특정 url로 가고 싶다면 다음과 같이 작성하면 된다. 

    def render_landing_page(self, request, form_submission=None, *args, **kwargs):
        url = #원하는 주소

        return redirect(url, permanent=False)

 

'Back-End > Wagtail, Django' 카테고리의 다른 글

Wagtail Rich Editor 기능 추가  (0) 2021.11.06
Wagtail Admin Page 한글 설정  (0) 2021.11.04
Wagtail Ajax  (0) 2021.10.29
Wagtail Custom Admin Menu  (0) 2021.10.28
Wagtail StreamField Queryset  (0) 2021.10.27

+ Recent posts