Dominic M.
Dominic M.

Reputation: 913

Query Wagtail Form Fields into Homepage

I was wondering if it was possible to query the form fields from a abstract wagtail form into page model. I would like to put a wagtail form on my homepage(page) model, but don't really understand how you would accomplish this, if it is even possible.

Any feedback is appreciated

home_page.html

  ...
  <form action="{% pageurl page %}" method="POST">
          {% csrf_token %}
      <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 %}

        <h3>Contact Form</h3><br>
        </div>

       {% for item in page.formPage.all %}
        {% for field in form.visible_fields %}
        <div class="col-md-6 col-sm-12">
          <div class="form-group">
            {% render_field field class+="form-control" %}
          </div>
        </div>
        {% endfor %}
      {% endfor %}
        </div>
        <div class="pull-center">
          <button type="submit" class="btn btn-contact mt-3">Submit</button>
        </div>
    </form>

models.py

imports removed

class HomePage(Page):
    firstheader = RichTextField(blank=True)
    firstbody = RichTextField(blank=True)
    registerbuttonurl = models.CharField(blank=True, max_length=250)
    secondheader = RichTextField(blank=True)
    secondbody = RichTextField(blank=True)
    registerlink = RichTextField(blank=True)

    def Form(self):
        return FormPage.objects.all()

    content_panels = Page.content_panels + [

        FieldPanel('firstheader', classname="full"),
        FieldPanel('firstbody', classname="full"),
        FieldPanel('registerbuttonurl'),
        FieldPanel('secondheader', classname="full"),
        FieldPanel('secondbody', classname="full"),
        FieldPanel('registerlink', classname="full"),
        InlinePanel('gallery_images', label="Certified Distributor Logos"),
    ]



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


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

    content_panels = AbstractEmailForm.content_panels + [
        FieldPanel('intro', 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):
        ...removed

Upvotes: 1

Views: 818

Answers (1)

gasman
gasman

Reputation: 25292

return FormPage.objects.all() won't work because the form fields are defined on one particular FormPage instance that you created in the admin, not on the FormPage class itself. You'll need something in your code to identify which FormPage you're referring to - I'd suggest giving it a unique slug (contact-us in this example) and retrieving it based on that.

class HomePage(Page):
    # ...
    def get_contact_form_page(self):
        return FormPage.objects.get(slug='contact-us')

    def get_contact_form(self):
        return self.get_contact_form_page().get_form()

Then, on your homepage template, you can access page.get_contact_form and render the resulting form in the same way as you would render it on the FormPage's own template:

{% with page.get_contact_form as form %}
    <form action="{% pageurl page.get_contact_form_page %}" method="POST">
        {% csrf_token %}
        {% for field in form.visible_fields %}
            ...
        {% endfor %}
    </form>
{% endwith %}

Note that the form action is set up to post to the form page; putting {% pageurl page %} here will cause it to post back to the homepage, and the homepage doesn't know how to handle form submissions. Similarly, the code for displaying validation error messages can be left out of the homepage template - if the user submits an invalid form, they'll be dropped onto the contact-us page rather than the homepage.

Upvotes: 4

Related Questions