mirror of
https://github.com/Hopiu/wagtail.git
synced 2026-05-11 16:53:10 +00:00
Fix code for pep8 compatibility
This commit is contained in:
parent
9d65be0d66
commit
4fc653ff9a
4 changed files with 125 additions and 92 deletions
|
|
@ -1,4 +1,4 @@
|
|||
import datetime
|
||||
import datetime
|
||||
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from .base import BaseFormProcessor
|
||||
|
|
@ -8,7 +8,7 @@ from wagtail.wagtailadmin import tasks
|
|||
class EmailFormProcessor(BaseFormProcessor):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
|
||||
@staticmethod
|
||||
def validate_usage(page):
|
||||
try:
|
||||
|
|
@ -17,7 +17,7 @@ class EmailFormProcessor(BaseFormProcessor):
|
|||
page._meta.get_field('from_address')
|
||||
except:
|
||||
raise ImproperlyConfigured("To use the EmailFormProcessor your Page must define the fields: subject, to_address and from_address.")
|
||||
|
||||
|
||||
def process(self, page, form):
|
||||
content = ', '.join([ x[1].label +': '+ form.data.get(x[0]) for x in form.fields.items() ])
|
||||
tasks.send_email_task.delay(page.subject, content, [page.to_address], page.from_address, )
|
||||
content = ', '.join([x[1].label + ': ' + form.data.get(x[0]) for x in form.fields.items()])
|
||||
tasks.send_email_task.delay(page.subject, content, [page.to_address], page.from_address,)
|
||||
|
|
|
|||
|
|
@ -3,15 +3,17 @@ from django.utils.datastructures import SortedDict
|
|||
from django.utils.text import slugify
|
||||
from unidecode import unidecode
|
||||
|
||||
|
||||
class FormBuilder():
|
||||
formfields = SortedDict()
|
||||
|
||||
def __init__(self, fields):
|
||||
for field in fields:
|
||||
options = self.get_options(field)
|
||||
f = getattr(self, "create_"+field.field_type+"_field" )(field, options)
|
||||
# unidecode will return an ascii string while slugify wants a unicode string
|
||||
# on the other hand, slugify returns a safe-string which will be converted
|
||||
# to a normal str
|
||||
f = getattr(self, "create_"+field.field_type+"_field")(field, options)
|
||||
# unidecode will return an ascii string while slugify wants a
|
||||
# unicode string on the other hand, slugify returns a safe-string
|
||||
# which will be converted to a normal str
|
||||
field_name = str(slugify(unicode(unidecode(field.label))))
|
||||
self.formfields[field_name] = f
|
||||
|
||||
|
|
@ -25,7 +27,7 @@ class FormBuilder():
|
|||
|
||||
def create_singleline_field(self, field, options):
|
||||
# TODO: This is a default value - it may need to be changed
|
||||
options['max_length'] = 255
|
||||
options['max_length'] = 255
|
||||
return django.forms.CharField(**options)
|
||||
|
||||
def create_multiline_field(self, field, options):
|
||||
|
|
@ -33,38 +35,53 @@ class FormBuilder():
|
|||
|
||||
def create_date_field(self, field, options):
|
||||
return django.forms.DateField(**options)
|
||||
|
||||
|
||||
def create_datetime_field(self, field, options):
|
||||
return django.forms.DateTimeField(**options)
|
||||
|
||||
def create_email_field(self, field, options):
|
||||
return django.forms.EmailField(**options)
|
||||
|
||||
|
||||
def create_url_field(self, field, options):
|
||||
return django.forms.URLField(**options)
|
||||
|
||||
def create_number_field(self, field, options):
|
||||
return django.forms.DecimalField(**options)
|
||||
|
||||
|
||||
def create_dropdown_field(self, field, options):
|
||||
options['choices'] = map(lambda x: (x.strip(),x.strip()), field.choices.split(','))
|
||||
options['choices'] = map(
|
||||
lambda x: (x.strip(), x.strip()),
|
||||
field.choices.split(',')
|
||||
)
|
||||
return django.forms.ChoiceField(**options)
|
||||
|
||||
|
||||
def create_radio_field(self, field, options):
|
||||
options['choices'] = map(lambda x: (x.strip(),x.strip()), field.choices.split(','))
|
||||
options['choices'] = map(
|
||||
lambda x: (x.strip(), x.strip()),
|
||||
field.choices.split(',')
|
||||
)
|
||||
return django.forms.ChoiceField(widget=django.forms.RadioSelect, **options)
|
||||
|
||||
|
||||
def create_checkboxes_field(self, field, options):
|
||||
options['choices'] = [ (x.strip(), x.strip()) for x in field.choices.split(',')]
|
||||
options['initial'] = [ x.strip() for x in field.default_value.split(',') ]
|
||||
return django.forms.MultipleChoiceField(widget=django.forms.CheckboxSelectMultiple, **options)
|
||||
|
||||
options['choices'] = [(x.strip(), x.strip()) for x in field.choices.split(',')]
|
||||
options['initial'] = [x.strip() for x in field.default_value.split(',')]
|
||||
return django.forms.MultipleChoiceField(
|
||||
widget=django.forms.CheckboxSelectMultiple, **options
|
||||
)
|
||||
|
||||
def create_checkbox_field(self, field, options):
|
||||
return django.forms.BooleanField(**options)
|
||||
|
||||
def get_form_class(self):
|
||||
return type('WagtailForm', (django.forms.Form,), self.formfields )
|
||||
|
||||
|
||||
def get_form_class(self):
|
||||
return type('WagtailForm', (django.forms.Form,), self.formfields)
|
||||
|
||||
|
||||
class SelectDateForm(django.forms.Form):
|
||||
date_from = django.forms.DateField(required=False, widget=django.forms.DateInput(attrs={'placeholder':'Date from'}))
|
||||
date_to = django.forms.DateField(required=False, widget=django.forms.DateInput(attrs={'placeholder':'Date to'}))
|
||||
date_from = django.forms.DateField(
|
||||
required=False,
|
||||
widget=django.forms.DateInput(attrs={'placeholder': 'Date from'})
|
||||
)
|
||||
date_to = django.forms.DateField(
|
||||
required=False,
|
||||
widget=django.forms.DateInput(attrs={'placeholder': 'Date to'})
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
from django.conf import settings
|
||||
from django.contrib.contenttypes import generic
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
|
|
@ -11,13 +10,12 @@ import re
|
|||
|
||||
from wagtail.wagtailcore.models import PageBase, Page, Orderable
|
||||
from wagtail.wagtailadmin.edit_handlers import FieldPanel, InlinePanel
|
||||
|
||||
from wagtail.wagtailforms.backends.email import EmailFormProcessor
|
||||
|
||||
from modelcluster.fields import ParentalKey
|
||||
|
||||
from .forms import FormBuilder
|
||||
|
||||
|
||||
FORM_FIELD_CHOICES = (
|
||||
('singleline', _('Single line text')),
|
||||
('multiline', _('Multi-line text')),
|
||||
|
|
@ -32,12 +30,13 @@ FORM_FIELD_CHOICES = (
|
|||
('datetime', _('Date/time')),
|
||||
)
|
||||
|
||||
|
||||
HTML_EXTENSION_RE = re.compile(r"(.*)\.html")
|
||||
|
||||
|
||||
class FormSubmission(models.Model):
|
||||
"""Data for a Form submission."""
|
||||
|
||||
|
||||
form_data = models.TextField()
|
||||
content_type = models.ForeignKey(ContentType)
|
||||
object_id = models.PositiveIntegerField()
|
||||
|
|
@ -45,23 +44,35 @@ class FormSubmission(models.Model):
|
|||
|
||||
submit_time = models.DateTimeField(auto_now_add=True)
|
||||
user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True)
|
||||
|
||||
|
||||
def get_data(self):
|
||||
return json.loads(self.form_data)
|
||||
|
||||
|
||||
def __unicode__(self):
|
||||
return self.form_data
|
||||
|
||||
|
||||
class AbstractFormFields(models.Model):
|
||||
"""Database Fields required for building a Django Form field."""
|
||||
|
||||
label = models.CharField(max_length=255, help_text=_('The label of the form field') )
|
||||
field_type = models.CharField(max_length=16, choices = FORM_FIELD_CHOICES)
|
||||
|
||||
label = models.CharField(
|
||||
max_length=255,
|
||||
help_text=_('The label of the form field')
|
||||
)
|
||||
field_type = models.CharField(max_length=16, choices=FORM_FIELD_CHOICES)
|
||||
required = models.BooleanField(default=True)
|
||||
choices = models.CharField(max_length=512, blank=True, help_text=_('Comma seperated list of choices. Only applicable in checkboxes, radio and dropdown.'))
|
||||
default_value = models.CharField(max_length=255, blank=True, help_text=_('Default value. Comma seperated values supported for checkboxes.'))
|
||||
choices = models.CharField(
|
||||
max_length=512,
|
||||
blank=True,
|
||||
help_text=_('Comma seperated list of choices. Only applicable in checkboxes, radio and dropdown.')
|
||||
)
|
||||
default_value = models.CharField(
|
||||
max_length=255,
|
||||
blank=True,
|
||||
help_text=_('Default value. Comma seperated values supported for checkboxes.')
|
||||
)
|
||||
help_text = models.CharField(max_length=255, blank=True)
|
||||
|
||||
|
||||
panels = [
|
||||
FieldPanel('label'),
|
||||
FieldPanel('field_type'),
|
||||
|
|
@ -70,14 +81,15 @@ class AbstractFormFields(models.Model):
|
|||
FieldPanel('default_value'),
|
||||
FieldPanel('help_text'),
|
||||
]
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
|
||||
FORM_MODEL_CLASSES = []
|
||||
_FORM_CONTENT_TYPES = []
|
||||
|
||||
|
||||
def get_form_types():
|
||||
global _FORM_CONTENT_TYPES
|
||||
if len(_FORM_CONTENT_TYPES) != len(FORM_MODEL_CLASSES):
|
||||
|
|
@ -85,58 +97,58 @@ def get_form_types():
|
|||
ContentType.objects.get_for_model(cls) for cls in FORM_MODEL_CLASSES
|
||||
]
|
||||
return _FORM_CONTENT_TYPES
|
||||
|
||||
|
||||
|
||||
class FormBase(PageBase):
|
||||
"""Metaclass for Forms"""
|
||||
def __init__(cls, name, bases, dct):
|
||||
super(FormBase, cls).__init__(name, bases, dct)
|
||||
|
||||
|
||||
if not cls.is_abstract:
|
||||
# register this type in the list of page content types
|
||||
FORM_MODEL_CLASSES.append(cls)
|
||||
# Check if form_processing_backend is ok
|
||||
if hasattr(cls, 'form_processing_backend'):
|
||||
cls.form_processing_backend.validate_usage(cls)
|
||||
|
||||
|
||||
|
||||
|
||||
class AbstractForm(Page):
|
||||
"""A Form Page. Pages implementing a form should inhert from it"""
|
||||
|
||||
__metaclass__ = FormBase
|
||||
|
||||
|
||||
form_builder = FormBuilder
|
||||
is_abstract = True # Don't display me in "Add"
|
||||
|
||||
is_abstract = True # Don't display me in "Add"
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(AbstractForm, self).__init__(*args, **kwargs)
|
||||
if not hasattr(self, 'landing_page_template'):
|
||||
if not hasattr(self, 'landing_page_template'):
|
||||
template_wo_ext = re.match(HTML_EXTENSION_RE, self.template).group(1)
|
||||
self.landing_page_template = template_wo_ext + '_landing.html'
|
||||
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
abstract = True
|
||||
|
||||
def serve(self, request):
|
||||
fb = self.form_builder(self.form_fields.all() )
|
||||
fb = self.form_builder(self.form_fields.all())
|
||||
form_class = fb.get_form_class()
|
||||
|
||||
|
||||
if request.method == 'POST':
|
||||
self.form = form_class(request.POST)
|
||||
|
||||
if self.form.is_valid():
|
||||
|
||||
if self.form.is_valid():
|
||||
# remove csrf_token from form.data
|
||||
form_data = dict(
|
||||
i for i in self.form.data.items()
|
||||
if i[0] != 'csrfmiddlewaretoken'
|
||||
i for i in self.form.data.items()
|
||||
if i[0] != 'csrfmiddlewaretoken'
|
||||
)
|
||||
|
||||
|
||||
submission = FormSubmission.objects.create(
|
||||
form_data = json.dumps(form_data),
|
||||
form_page = self,
|
||||
user = request.user,
|
||||
form_data=json.dumps(form_data),
|
||||
form_page=self,
|
||||
user=request.user,
|
||||
)
|
||||
|
||||
|
||||
# If we have a form_processing_backend call its process method
|
||||
if hasattr(self, 'form_processing_backend'):
|
||||
form_processor = self.form_processing_backend()
|
||||
|
|
@ -154,38 +166,40 @@ class AbstractForm(Page):
|
|||
'self': self,
|
||||
'form': self.form,
|
||||
})
|
||||
|
||||
|
||||
|
||||
class AbstractEmailForm(AbstractForm):
|
||||
"""A Form Page that sends email. Pages implementing a form to be send to an email should inherit from it"""
|
||||
is_abstract = True # Don't display me in "Add"
|
||||
is_abstract = True # Don't display me in "Add"
|
||||
form_processing_backend = EmailFormProcessor
|
||||
|
||||
|
||||
to_address = models.CharField(max_length=255, )
|
||||
from_address = models.CharField(max_length=255, blank=True)
|
||||
subject = models.CharField(max_length=255, )
|
||||
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
|
||||
######## TEST
|
||||
|
||||
|
||||
# TEST
|
||||
class ConcreteFormFields(Orderable, AbstractFormFields):
|
||||
page = ParentalKey('wagtailforms.ConcreteForm', related_name='form_fields')
|
||||
|
||||
class ConcreteForm(AbstractForm):
|
||||
|
||||
class ConcreteForm(AbstractForm):
|
||||
thank_you = models.CharField(max_length=255)
|
||||
|
||||
|
||||
ConcreteForm.content_panels = [
|
||||
FieldPanel('title', classname="full title"),
|
||||
FieldPanel('thank_you', classname="full"),
|
||||
InlinePanel(ConcreteForm, 'form_fields', label="Form Fields"),
|
||||
]
|
||||
|
||||
########
|
||||
|
||||
class ConcreteEmailFormFields(Orderable, AbstractFormFields):
|
||||
page = ParentalKey('wagtailforms.ConcreteEmailForm', related_name='form_fields')
|
||||
|
||||
|
||||
class ConcreteEmailForm(AbstractEmailForm):
|
||||
thank_you = models.CharField(max_length=255)
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ from wagtail.wagtailcore.models import Page
|
|||
from wagtail.wagtailforms.models import FormSubmission, get_form_types
|
||||
from wagtail.wagtailforms.forms import SelectDateForm
|
||||
|
||||
|
||||
def get_form_type_from_url_params(app_name, model_name):
|
||||
"""
|
||||
Retrieve a form type from an app_name / model_name combo.
|
||||
|
|
@ -34,20 +35,21 @@ def get_form_type_from_url_params(app_name, model_name):
|
|||
def index(request):
|
||||
form_types = get_form_types()
|
||||
form_pages = Page.objects.filter(content_type__in=form_types)
|
||||
|
||||
|
||||
return render(request, 'wagtailforms/index.html', {
|
||||
'form_pages': form_pages,
|
||||
})
|
||||
|
||||
|
||||
@permission_required('wagtailadmin.access_admin')
|
||||
def list_submissions(request, app_label, model, id):
|
||||
|
||||
model = get_form_type_from_url_params(app_label, model).model_class()
|
||||
form_page = get_object_or_404(model, id=id)
|
||||
|
||||
#submissions = FormSubmission.objects.filter(form_page=form_page)
|
||||
submissions = FormSubmission.objects.filter(content_type = form_page.content_type, object_id=form_page.id)
|
||||
|
||||
submissions = FormSubmission.objects.filter(
|
||||
content_type=form_page.content_type, object_id=form_page.id
|
||||
)
|
||||
|
||||
select_date_form = SelectDateForm(request.GET)
|
||||
if select_date_form.is_valid():
|
||||
date_from = select_date_form.cleaned_data.get('date_from')
|
||||
|
|
@ -57,35 +59,35 @@ def list_submissions(request, app_label, model, id):
|
|||
if date_to:
|
||||
date_to += datetime.timedelta(days=1)
|
||||
if date_from and date_to:
|
||||
submissions=submissions.filter(submit_time__range=[date_from, date_to] )
|
||||
submissions = submissions.filter(submit_time__range=[date_from, date_to])
|
||||
elif date_from and not date_to:
|
||||
submissions=submissions.filter(submit_time__gte=date_from)
|
||||
submissions = submissions.filter(submit_time__gte=date_from)
|
||||
elif not date_from and date_to:
|
||||
submissions=submissions.filter(submit_time__lte=date_to)
|
||||
|
||||
if request.GET.get('action')=='CSV':
|
||||
submissions = submissions.filter(submit_time__lte=date_to)
|
||||
|
||||
if request.GET.get('action') == 'CSV':
|
||||
# return a CSV instead
|
||||
response = HttpResponse(content_type='text/csv; charset=utf-8')
|
||||
response['Content-Disposition'] = 'attachment;filename=export.csv'
|
||||
writer = unicodecsv.writer(response, encoding='utf-8')
|
||||
|
||||
|
||||
if submissions:
|
||||
extra_keys = json.loads(submissions[0].form_data).keys()
|
||||
|
||||
header_row = ['Submission date', 'user',]
|
||||
|
||||
header_row = ['Submission date', 'user']
|
||||
header_row.extend(extra_keys)
|
||||
writer.writerow(header_row)
|
||||
writer.writerow(header_row)
|
||||
for s in submissions:
|
||||
data_row = [s.submit_time, s.user]
|
||||
form_data = json.loads(s.form_data)
|
||||
for ek in extra_keys:
|
||||
data_row.append( form_data.get(ek) )
|
||||
data_row.append(form_data.get(ek))
|
||||
writer.writerow(data_row)
|
||||
return response
|
||||
|
||||
|
||||
p = request.GET.get('p', 1)
|
||||
paginator = Paginator(submissions, 20)
|
||||
|
||||
|
||||
try:
|
||||
submissions = paginator.page(p)
|
||||
except PageNotAnInteger:
|
||||
|
|
|
|||
Loading…
Reference in a new issue