Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions docs/forms.rst
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
Custom Form Functionality
=========================
Form Customisation
==================

Currently we have defined two different types of forms, one which just
enables saving the submission and one to addionally email the results of
enables saving the submission and one to additionally email the results of
the submission.

You can easily add your own all you have to do is create a model that
inherits from ``wagtailstreamforms.models.BaseForm`` add any addional fields or properties and
inherits from ``wagtailstreamforms.models.BaseForm`` add any additional fields or properties and
this will be added to the cms admin area.

Example:
Expand All @@ -31,4 +31,10 @@ Reference
:members:

.. autoclass:: wagtailstreamforms.models.EmailForm
:members:

.. autoclass:: wagtailstreamforms.models.AbstractFormSubmission
:members:

.. autoclass:: wagtailstreamforms.models.FormSubmission
:members:
4 changes: 2 additions & 2 deletions docs/templates.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Creating Form Templates
=======================
Form Templates
==============

You can create your own form templates to use against any form in the system, providing a vast array of ways to
create, style and submit your forms.
Expand Down
14 changes: 9 additions & 5 deletions tests/models/test_base_form.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from model_utils.managers import InheritanceManager
from modelcluster.models import ClusterableModel

from wagtailstreamforms.models import BaseForm, FormField
from wagtailstreamforms.models import BaseForm, FormField, FormSubmission

from ..test_case import AppTestCase

Expand Down Expand Up @@ -132,7 +132,11 @@ def test_get_form(self):
'regexfield'
]
self.assertEqual(actual_fields, expected_fields)


def test_get_submission_class(self):
form = self.test_form()
self.assertEquals(form.get_submission_class(), FormSubmission)

def test_process_form_submission__saves_record_when_store_submission_is_true(self):
form = self.test_form(True)
data = {
Expand All @@ -154,8 +158,8 @@ def test_process_form_submission__saves_record_when_store_submission_is_true(sel
assert form_class.is_valid()
form.process_form_submission(form_class)
saved_form_data = json.dumps(form_class.cleaned_data, cls=DjangoJSONEncoder)
self.assertEquals(form.formsubmission_set.count(), 1)
self.assertEquals(form.formsubmission_set.all()[0].form_data, saved_form_data)
self.assertEquals(form.get_submission_class().objects.count(), 1)
self.assertEquals(form.get_submission_class().objects.all()[0].form_data, saved_form_data)

def test_process_form_submission__does_not_save_record_when_store_submission_is_false(self):
form = self.test_form()
Expand All @@ -177,4 +181,4 @@ def test_process_form_submission__does_not_save_record_when_store_submission_is_
form_class = form.get_form(data)
assert form_class.is_valid()
form.process_form_submission(form_class)
self.assertEquals(form.formsubmission_set.count(), 0)
self.assertEquals(form.get_submission_class().objects.count(), 0)
2 changes: 1 addition & 1 deletion tests/models/test_email_form.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,4 @@ def test_process_form_submission__still_saves_submission(self):
form_class = form.get_form({'name': 'foo'})
assert form_class.is_valid()
form.process_form_submission(form_class)
self.assertEquals(form.formsubmission_set.count(), 1)
self.assertEquals(form.get_submission_class().objects.count(), 1)
8 changes: 4 additions & 4 deletions tests/models/test_form_submission.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
from django.db import models

from wagtailstreamforms.models import BaseForm, FormSubmission
from wagtailstreamforms.models import AbstractFormSubmission, BaseForm, FormSubmission

from ..test_case import AppTestCase


class ModelGenericTests(AppTestCase):

def test_inheritance(self):
self.assertTrue(issubclass(FormSubmission, models.Model))
self.assertTrue(issubclass(FormSubmission, AbstractFormSubmission))

def test_str(self):
model = FormSubmission(form_data='{"foo": 1}')
Expand Down Expand Up @@ -45,11 +45,11 @@ def test_get_data(self):
expected_data = {"foo": 1, "submit_time": model.submit_time}
self.assertEquals(model.get_data(), expected_data)

def test_get_data_blank_edge_case(self):
def test_get_data_blank(self):
form = BaseForm.objects.create(
name='Form',
template_name='streamforms/form_block.html'
)
model = FormSubmission.objects.create(form_data='', form=form)
model = FormSubmission.objects.create(form_data='{}', form=form)
expected_data = {"submit_time": model.submit_time}
self.assertEquals(model.get_data(), expected_data)
2 changes: 1 addition & 1 deletion tests/models/test_mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def test_post_saves_submission(self):

SomePage().serve(fake_request)

self.assertEquals(form.formsubmission_set.count(), 1)
self.assertEquals(form.get_submission_class().objects.count(), 1)

def test_invalid_form_id_does_not_break_view(self):
form = self.test_form()
Expand Down
2 changes: 1 addition & 1 deletion wagtailstreamforms/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from .form import BaseForm, BasicForm, EmailForm
from .form_field import FormField
from .mixins import StreamFormPageMixin
from .submission import FormSubmission
from .submission import AbstractFormSubmission, FormSubmission
from .validators import RegexFieldValidator
12 changes: 11 additions & 1 deletion wagtailstreamforms/models/form.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,16 @@ def get_form(self, *args, **kwargs):

return form_class(*args, **form_params)

def get_submission_class(self):
"""
Returns submission class.

You can override this method to provide custom submission class.
Your class must be inherited from AbstractFormSubmission.
"""

return FormSubmission

def process_form_submission(self, form):
"""
Accepts form instance with submitted data.
Expand All @@ -119,7 +129,7 @@ def process_form_submission(self, form):
"""

if self.store_submission:
FormSubmission.objects.create(
return self.get_submission_class().objects.create(
form_data=json.dumps(form.cleaned_data, cls=DjangoJSONEncoder),
form=self
)
Expand Down
28 changes: 21 additions & 7 deletions wagtailstreamforms/models/submission.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@
from django.utils.translation import ugettext_lazy as _


class FormSubmission(models.Model):
""" Data for a Form submission. """
class AbstractFormSubmission(models.Model):
"""
Data for a form submission.

You can create custom submission model based on this abstract model.
For example, if you need to save additional data or a reference to a user.
"""

form_data = models.TextField()
form = models.ForeignKey(
Expand All @@ -18,18 +23,27 @@ class FormSubmission(models.Model):
)

def get_data(self):
try:
form_data = json.loads(self.form_data)
except ValueError:
form_data = {}
"""
Returns dict with form data.

You can override this method to add additional data.
"""
form_data = json.loads(self.form_data)

form_data.update({'submit_time': self.submit_time, })
form_data.update(
{'submit_time': self.submit_time, }
)

return form_data

def __str__(self):
return self.form_data

class Meta:
abstract = True
ordering = ['-submit_time', ]
verbose_name = _('form submission')


class FormSubmission(AbstractFormSubmission):
""" Data for a Form submission. """
3 changes: 2 additions & 1 deletion wagtailstreamforms/views/delete.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ class SubmissionDeleteView(DeleteView):

def get_submissions(self):
submission_ids = self.request.GET.getlist('selected-submissions')
return self.object.formsubmission_set.filter(id__in=submission_ids)
submission_class = self.object.get_submission_class()
return submission_class._default_manager.filter(id__in=submission_ids)

def get_context_data(self, **kwargs):
context = super(SubmissionDeleteView, self).get_context_data(**kwargs)
Expand Down
3 changes: 2 additions & 1 deletion wagtailstreamforms/views/list.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ def csv(self):
return response

def get_queryset(self):
self.queryset = self.object.formsubmission_set.all()
submission_class = self.object.get_submission_class()
self.queryset = submission_class._default_manager.filter(form=self.object)

# filter the queryset by the required dates
if self.filter_form.is_valid():
Expand Down
6 changes: 4 additions & 2 deletions wagtailstreamforms/wagtail_hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,12 @@ class FormModelAdmin(ModelAdmin):
url_helper_class = FormURLHelper

def latest_submission_date(self, obj):
return obj.formsubmission_set.latest('submit_time').submit_time
submission_class = obj.get_submission_class()
return submission_class._default_manager.filter(form=obj).latest('submit_time').submit_time

def number_of_submissions(self, obj):
return obj.formsubmission_set.count()
submission_class = obj.get_submission_class()
return submission_class._default_manager.filter(form=obj).count()


def _get_valid_subclasses(cls):
Expand Down