Submission Methods¶
Form submissions are handled by the means of a wagtail before_serve_page
hook. The built in hook at
wagtailstreamforms.wagtail_hooks.process_form
looks for a form in the post request,
and either:
- processes it redirecting back to the current page or defined page in the form setup.
- or renders the current page with any validation error.
If no form was posted then the page serves in the usual manner.
Note
Currently the hook expects the form to be posting to the same page it exists on.
Providing your own submission method¶
If you do not want the current hook to be used you need to disable it by setting the
WAGTAILSTREAMFORMS_ENABLE_FORM_PROCESSING
to False
in your settings:
WAGTAILSTREAMFORMS_ENABLE_FORM_PROCESSING = False
With this set no forms will be processed of any kind and you are free to process them how you feel fit.
A basic hook example¶
@hooks.register('before_serve_page')
def process_form(page, request, *args, **kwargs):
""" Process the form if there is one, if not just continue. """
# only process if settings.WAGTAILSTREAMFORMS_ENABLE_FORM_PROCESSING is True
if not get_setting('ENABLE_FORM_PROCESSING'):
return
if request.method == 'POST':
form_def = get_form_instance_from_request(request)
if form_def:
form = form_def.get_form(request.POST, request.FILES, page=page, user=request.user)
context = page.get_context(request, *args, **kwargs)
if form.is_valid():
# process the form submission
form_def.process_form_submission(form)
# create success message
if form_def.success_message:
messages.success(request, form_def.success_message, fail_silently=True)
# redirect to the page defined in the form
# or the current page as a fallback - this will avoid refreshing and submitting again
redirect_page = form_def.post_redirect_page or page
return redirect(redirect_page.get_url(request), context=context)
else:
# update the context with the invalid form and serve the page
context.update({
'invalid_stream_form_reference': form.data.get('form_reference'),
'invalid_stream_form': form
})
# create error message
if form_def.error_message:
messages.error(request, form_def.error_message, fail_silently=True)
return TemplateResponse(
request,
page.get_template(request, *args, **kwargs),
context
)
Supporting ajax requests¶
The only addition here from the basic example is just the if request.is_ajax:
and the JsonResponse
parts.
We are just making it respond with this if the request was ajax.
@hooks.register('before_serve_page')
def process_form(page, request, *args, **kwargs):
""" Process the form if there is one, if not just continue. """
if request.method == 'POST':
form_def = get_form_instance_from_request(request)
if form_def:
form = form_def.get_form(request.POST, request.FILES, page=page, user=request.user)
context = page.get_context(request, *args, **kwargs)
if form.is_valid():
# process the form submission
form_def.process_form_submission(form)
# if the request is_ajax then just return a success message
if request.is_ajax():
return JsonResponse({'message': form_def.success_message or 'success'})
# insert code to serve page if not ajax (as original)
else:
# if the request is_ajax then return an error message and the form errors
if request.is_ajax():
return JsonResponse({
'message': form_def.error_message or 'error',
'errors': form.errors
})
# insert code to serve page if not ajax (as original)
Add some javascript somewhere to process the form via ajax:
<form>...</form>
<script>
$("#id_streamforms_{{ form.initial.form_id }}").submit(function(e) {
$.ajax({
type: "POST",
url: ".",
data: $(this).serialize(),
success: function(data) {
// do something with data
console.log(data);
},
error: function(data) {
// do something with data
console.log(data);
}
});
e.preventDefault();
});
</script>