Implementing @check_honeypot on Django Wagtail Form

Dominic M. picture Dominic M. · Jun 20, 2019 · Viewed 8.5k times · Source

I am trying to implement Honeypot into a Wagtail email form, but I don't understand how to add the @check_honeypot decorator to a class in models.py, which checks the honeypotfor validity.

To set up Honeypot, it requires that I add the @check_honeypot decorator to the form view in my views.py. Unfortunately, wagtail does not utilize views.py and instead the form is built in the models.py.

How to I implement honeypot decorator onto a Wagtail form?

Honeypot repo: https://github.com/jamesturk/django-honeypot Snippet from honeypot instructions:

To ensure that the honeypot field is both present and correct you will >need to use check_honeypot decorator from honeypot.decorators:

from honeypot.decorators import check_honeypot

@check_honeypot(field_name='hp_field_name') def post_comment(request): ... @check_honeypot def other_post_view(request): ...

SOLUTION:

@method_decorator(check_honeypot)
def render_landing_page

models.py

class FormField(AbstractFormField):
    page = ParentalKey('FormPage', on_delete=models.CASCADE, related_name='form_fields')


class FormPage(AbstractEmailForm):
    header = RichTextField(blank=True)
    body = RichTextField(blank=True)
    header_two = RichTextField(blank=True)
    body_two = RichTextField(blank=True)
    header_three = RichTextField(blank=True)
    body_three = RichTextField(blank=True)
    address = RichTextField(blank=True)
    form_header = models.CharField(blank=True, max_length=100)
    thank_you_text = RichTextField(blank=True)

    content_panels = AbstractEmailForm.content_panels + [
        FieldPanel('header', classname="full"),
        FieldPanel('body', classname='full'),
        FieldPanel('header_two', classname="full"),
        FieldPanel('body_two', classname='full'),
        FieldPanel('header_three', classname="full"),
        FieldPanel('body_three', classname='full'),
        FieldPanel('address', classname='full'),
        FieldPanel('form_header', classname='full'),
        InlinePanel('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"),
    ]


    thank_you_page = models.ForeignKey(
        'wagtailcore.Page',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
    )

    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)

    content_panels = AbstractEmailForm.content_panels + [
        FieldPanel('header', classname="full"),
        FieldPanel('body', classname='full'),
        FieldPanel('header_two', classname="full"),
        FieldPanel('body_two', classname='full'),
        FieldPanel('header_three', classname="full"),
        FieldPanel('body_three', classname='full'),
        FieldPanel('address', classname='full'),
        FieldPanel('form_header', classname='full'),
        InlinePanel('form_fields'),
        FieldPanel('thank_you_text', classname='full'),
        PageChooserPanel('thank_you_page'),
        MultiFieldPanel([
            FieldRowPanel([
                FieldPanel('from_address', classname='col6'),
                FieldPanel('to_address', classname='col6'),
            ]),
            FieldPanel('subject'),
        ], 'Email'),
    ]

form.html

    <section class="contact-background-lg" >
      <div class="container px-0">
      <div class="card p-m-5-0">
          <form action="{% pageurl page %}" method="POST">
              {% csrf_token %}
              {% render_honeypot_field "phonenumber" %}
              <div class="row">
                  <div class="col-md-12 col-sm-12">
                    {% if form.non_field_errors %}
                        <div class="alert alert-danger" role="alert">
                          {% for error in form.non_field_errors %}
                            {{ error }}
                          {% endfor %}
                        </div>
                    {% endif %}
                    <div class="card-title text-primary">
                      <h2><strong>{{ page.form_header }}</strong></h2><p class="pb-2 text-muted">Please complete the form below to receive a response within 24 hours.</p>
                      <hr>
                      <br>
                    </div>
                  </div>
                  {% for field in form.visible_fields %}
                  <div class="col-md-6 col-sm-12">
                    <div class="form-group pt-3">
                      {{ field.label_tag }}
                      {% render_field field class+="form-control" %}
                    </div>
                  </div>
                  {% endfor %}
              </div>
              <div class="pull-center">
                <button type="submit" class="btn btn-primary-alt py-3 mt-3" style="width: 8rem;">Submit</button>
              </div>
          </form>
      </div>
    </div>
  </section>

Answer