Use Django's SessionWizardView and get rid of our included one

This commit is contained in:
Roberto Rosario
2014-06-26 15:31:47 -04:00
parent 3b73936723
commit 97037e8e56
5 changed files with 81 additions and 155 deletions

View File

@@ -1,23 +1,23 @@
from __future__ import absolute_import
from django.shortcuts import redirect
from django.utils.translation import ugettext_lazy as _
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.contrib import messages
from django.contrib.contenttypes.models import ContentType
from django.core.urlresolvers import reverse
from django.utils.http import urlencode
from django.contrib.auth.views import login
from django.utils.simplejson import dumps, loads
from django.contrib.auth.views import password_change
from django.contrib.auth.models import User
from django.contrib.auth.views import login, password_change
from django.contrib.contenttypes.models import ContentType
from django.conf import settings
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
from django.shortcuts import redirect, render_to_response
from django.template import RequestContext
from django.utils.http import urlencode
from django.utils.simplejson import dumps, loads
from django.utils.translation import ugettext_lazy as _
from permissions.models import Permission
from .conf.settings import LOGIN_METHOD
from .forms import (ChoiceForm, UserForm, UserForm_view, LicenseForm,
EmailAuthenticationForm)
from .conf.settings import LOGIN_METHOD
def multi_object_action_view(request):
@@ -253,3 +253,13 @@ def password_change_done(request):
messages.success(request, _(u'Your password has been successfully changed.'))
return redirect('current_user_details')
class MayanPermissionCheckMixin(object):
permissions_required = None
def dispatch(self, request, *args, **kwargs):
if self.permissions_required:
Permission.objects.check_permissions(self.request.user, self.permissions_required)
return super(MayanPermissionCheckMixin, self).dispatch(request, *args, **kwargs)

View File

@@ -1,88 +0,0 @@
"""Common abstract classes for forms."""
try:
import cPickle as pickle
except ImportError:
import pickle
from django import forms
from django.conf import settings
from django.contrib.formtools.wizard import FormWizard
from django.forms.forms import BoundField
from django.forms.formsets import BaseFormSet
from django.utils.hashcompat import md5_constructor
__all__ = ('security_hash', 'BoundFormWizard')
def security_hash_new(form, exclude=None, *args):
"""
Calculates a security hash for the given Form/FormSet instance.
This creates a list of the form field names/values in a deterministic
order, pickles the result with the SECRET_KEY setting, then takes an md5
hash of that.
"""
data = []
if exclude is None:
exclude = ()
if isinstance(form, BaseFormSet):
for _form in form.forms + [form.management_form]:
for bf in _form:
value = bf.field.clean(bf.data) or ''
if isinstance(value, basestring):
value = value.strip()
data.append((bf.name, value))
else:
for bf in form:
if bf.name in exclude:
continue
value = bf.field.clean(bf.data) or ''
if isinstance(value, basestring):
value = value.strip()
data.append((bf.name, value))
data.extend(args)
data.append(settings.SECRET_KEY)
# Use HIGHEST_PROTOCOL because it's the most efficient. It requires
# Python 2.3, but Django requires 2.3 anyway, so that's OK.
pickled = pickle.dumps(data, pickle.HIGHEST_PROTOCOL)
return md5_constructor(pickled).hexdigest()
class BoundFormWizard(FormWizard):
"""
Render prev_fields as a list of bound form fields in the template
context rather than raw html.
"""
def security_hash(self, request, form):
"""
Calculates the security hash for the given HttpRequest and
Form/FormSet instances.
Subclasses may want to take into account request-specific information,
such as the IP address.
"""
return security_hash_new(form)
def render(self, form, request, step, context=None):
'Renders the given Form object, returning an HttpResponse.'
old_data = request.POST
prev_fields = []
if old_data:
for i in range(step):
old_form = self.get_form(i, old_data)
hash_name = 'hash_%s' % i
if isinstance(old_form, BaseFormSet):
for _form in old_form.forms + [old_form.management_form]:
prev_fields.extend([bf for bf in _form])
else:
prev_fields.extend([bf for bf in old_form])
hash_field = forms.Field(initial=old_data.get(hash_name,
self.security_hash(request, old_form)))
bf = BoundField(forms.Form(), hash_field, hash_name)
prev_fields.append(bf)
return self.render_template(request, form, prev_fields, step, context)

View File

@@ -1,9 +1,10 @@
from __future__ import absolute_import
from django.conf.urls.defaults import patterns, url
from django.conf.urls import patterns, url
from .literals import (SOURCE_CHOICE_WEB_FORM, SOURCE_CHOICE_STAGING,
SOURCE_CHOICE_WATCH)
from .wizards import DocumentCreateWizard
urlpatterns = patterns('sources.views',
url(r'^staging_file/type/(?P<source_type>\w+)/(?P<source_id>\d+)/(?P<staging_file_id>\w+)/preview/$', 'staging_file_preview', (), 'staging_file_preview'),
@@ -34,6 +35,6 @@ urlpatterns = patterns('sources.views',
# Document create views
url(r'^create/from/local/multiple/$', 'document_create', (), 'document_create_multiple'),
url(r'^create/from/local/multiple/$', DocumentCreateWizard.as_view(), name='document_create_multiple'),
url(r'^(?P<document_id>\d+)/create/siblings/$', 'document_create_siblings', (), 'document_create_siblings'),
)

View File

@@ -40,14 +40,6 @@ from .staging import create_staging_file_class
from .wizards import DocumentCreateWizard
def document_create(request):
Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_CREATE])
wizard = DocumentCreateWizard(form_list=[DocumentTypeSelectForm, MetadataSelectionForm, MetadataFormSet])
return wizard(request)
def document_create_siblings(request, document_id):
Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_CREATE])

View File

@@ -1,25 +1,40 @@
# DEPRECATION: This module is scheduled to be delete once the update to Django 1.6.X is complete
from __future__ import absolute_import
from django.contrib.formtools.wizard.views import SessionWizardView
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
from django.utils.http import urlencode
from django.utils.translation import ugettext_lazy as _
from common.wizard import BoundFormWizard
from common.views import MayanPermissionCheckMixin
from documents.forms import DocumentTypeSelectForm
from documents.permissions import PERMISSION_DOCUMENT_CREATE
from metadata.forms import MetadataSelectionForm, MetadataFormSet
class DocumentCreateWizard(BoundFormWizard):
class DocumentCreateWizard(MayanPermissionCheckMixin, SessionWizardView):
form_list = [DocumentTypeSelectForm, MetadataSelectionForm, MetadataFormSet]
template_name = 'generic_wizard.html'
extra_context = {}
permissions_required = [PERMISSION_DOCUMENT_CREATE]
@staticmethod
def has_metadata_types(wizard):
# Skip the 3rd step if no metadata types or sets are selected
try:
return wizard.get_cleaned_data_for_step('1')['metadata_sets'] or wizard.get_cleaned_data_for_step('1')['metadata_types']
except TypeError:
return False
def generate_metadata_initial_values(self):
initial = []
for metadata_type in self.metadata_types:
for metadata_type in self.get_cleaned_data_for_step('1')['metadata_types']:
initial.append({
'metadata_type': metadata_type,
})
for metadata_set in self.metadata_sets:
for metadata_set in self.get_cleaned_data_for_step('1')['metadata_sets']:
for metadata_set_item in metadata_set.metadatasetitem_set.all():
data = {
'metadata_type': metadata_set_item.metadata_type,
@@ -30,53 +45,49 @@ class DocumentCreateWizard(BoundFormWizard):
return initial
def __init__(self, *args, **kwargs):
self.query_dict = {}
self.step_titles = kwargs.pop('step_titles', [
super(DocumentCreateWizard, self).__init__(*args, **kwargs)
self.condition_dict = {'2': DocumentCreateWizard.has_metadata_types}
self.step_titles = [
_(u'step 1 of 3: Document type'),
_(u'step 2 of 3: Metadata selection'),
_(u'step 3 of 3: Document metadata'),
])
]
super(DocumentCreateWizard, self).__init__(*args, **kwargs)
def get_form_initial(self, step):
if step == '1':
try:
return {'document_type': self.get_cleaned_data_for_step('0')['document_type']}
except TypeError:
return {}
elif step == '2':
return self.generate_metadata_initial_values()
def render_template(self, request, form, previous_fields, step, context=None):
context = {
'step_title': self.extra_context['step_titles'][step],
return self.initial_dict.get(step, {})
def get_context_data(self, form, **kwargs):
context = super(DocumentCreateWizard, self).get_context_data(form=form, **kwargs)
context.update({
'step_title': self.step_titles[self.steps.step0],
'submit_label': _(u'Next step'),
'submit_icon_famfam': 'arrow_right',
}
return super(DocumentCreateWizard, self).render_template(
request, form, previous_fields, step, context
)
})
return context
def parse_params(self, request, *args, **kwargs):
self.extra_context = {'step_titles': self.step_titles}
def done(self, form_list):
query_dict = {}
try:
query_dict['document_type_id'] = self.get_cleaned_data_for_step('0')['document_type'].pk
except AttributeError:
pass
def process_step(self, request, form, step):
if isinstance(form, DocumentTypeSelectForm):
self.document_type = form.cleaned_data['document_type']
self.initial = {1: {'document_type': self.document_type}}
try:
for identifier, metadata in enumerate(self.get_cleaned_data_for_step('2')):
query_dict['metadata%s_id' % identifier] = metadata['id']
query_dict['metadata%s_value' % identifier] = metadata['value']
except TypeError:
pass
if isinstance(form, MetadataSelectionForm):
self.metadata_sets = form.cleaned_data['metadata_sets']
self.metadata_types = form.cleaned_data['metadata_types']
initial_data = self.generate_metadata_initial_values()
self.initial = {2: initial_data}
if not initial_data:
# If there is no metadata selected, finish wizard
self.form_list = [DocumentTypeSelectForm, MetadataSelectionForm]
if isinstance(form, MetadataFormSet):
for identifier, metadata in enumerate(form.cleaned_data):
self.query_dict['metadata%s_id' % identifier] = metadata['id']
self.query_dict['metadata%s_value' % identifier] = metadata['value']
def get_template(self, step):
return 'generic_wizard.html'
def done(self, request, form_list):
if self.document_type:
self.query_dict['document_type_id'] = self.document_type.pk
url = '?'.join([reverse('upload_interactive'), urlencode(self.query_dict, doseq=True)])
url = '?'.join([reverse('upload_interactive'), urlencode(query_dict, doseq=True)])
return HttpResponseRedirect(url)