Use Django's SessionWizardView and get rid of our included one
This commit is contained in:
@@ -1,23 +1,23 @@
|
|||||||
from __future__ import absolute_import
|
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 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.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.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,
|
from .forms import (ChoiceForm, UserForm, UserForm_view, LicenseForm,
|
||||||
EmailAuthenticationForm)
|
EmailAuthenticationForm)
|
||||||
from .conf.settings import LOGIN_METHOD
|
|
||||||
|
|
||||||
|
|
||||||
def multi_object_action_view(request):
|
def multi_object_action_view(request):
|
||||||
@@ -237,7 +237,7 @@ def password_change_view(request):
|
|||||||
Password change wrapper for better control
|
Password change wrapper for better control
|
||||||
"""
|
"""
|
||||||
context={'title': _(u'Current user password change')}
|
context={'title': _(u'Current user password change')}
|
||||||
|
|
||||||
return password_change(
|
return password_change(
|
||||||
request,
|
request,
|
||||||
extra_context=context,
|
extra_context=context,
|
||||||
@@ -253,3 +253,13 @@ def password_change_done(request):
|
|||||||
|
|
||||||
messages.success(request, _(u'Your password has been successfully changed.'))
|
messages.success(request, _(u'Your password has been successfully changed.'))
|
||||||
return redirect('current_user_details')
|
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)
|
||||||
|
|||||||
@@ -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)
|
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
from __future__ import absolute_import
|
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,
|
from .literals import (SOURCE_CHOICE_WEB_FORM, SOURCE_CHOICE_STAGING,
|
||||||
SOURCE_CHOICE_WATCH)
|
SOURCE_CHOICE_WATCH)
|
||||||
|
from .wizards import DocumentCreateWizard
|
||||||
|
|
||||||
urlpatterns = patterns('sources.views',
|
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'),
|
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
|
# 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'),
|
url(r'^(?P<document_id>\d+)/create/siblings/$', 'document_create_siblings', (), 'document_create_siblings'),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -40,14 +40,6 @@ from .staging import create_staging_file_class
|
|||||||
from .wizards import DocumentCreateWizard
|
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):
|
def document_create_siblings(request, document_id):
|
||||||
Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_CREATE])
|
Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_CREATE])
|
||||||
|
|
||||||
|
|||||||
@@ -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 __future__ import absolute_import
|
||||||
|
|
||||||
|
from django.contrib.formtools.wizard.views import SessionWizardView
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
from django.utils.http import urlencode
|
from django.utils.http import urlencode
|
||||||
from django.utils.translation import ugettext_lazy as _
|
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.forms import DocumentTypeSelectForm
|
||||||
|
from documents.permissions import PERMISSION_DOCUMENT_CREATE
|
||||||
from metadata.forms import MetadataSelectionForm, MetadataFormSet
|
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):
|
def generate_metadata_initial_values(self):
|
||||||
initial = []
|
initial = []
|
||||||
for metadata_type in self.metadata_types:
|
|
||||||
|
for metadata_type in self.get_cleaned_data_for_step('1')['metadata_types']:
|
||||||
initial.append({
|
initial.append({
|
||||||
'metadata_type': metadata_type,
|
'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():
|
for metadata_set_item in metadata_set.metadatasetitem_set.all():
|
||||||
data = {
|
data = {
|
||||||
'metadata_type': metadata_set_item.metadata_type,
|
'metadata_type': metadata_set_item.metadata_type,
|
||||||
@@ -30,53 +45,49 @@ class DocumentCreateWizard(BoundFormWizard):
|
|||||||
return initial
|
return initial
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
self.query_dict = {}
|
super(DocumentCreateWizard, self).__init__(*args, **kwargs)
|
||||||
self.step_titles = kwargs.pop('step_titles', [
|
|
||||||
|
self.condition_dict = {'2': DocumentCreateWizard.has_metadata_types}
|
||||||
|
|
||||||
|
self.step_titles = [
|
||||||
_(u'step 1 of 3: Document type'),
|
_(u'step 1 of 3: Document type'),
|
||||||
_(u'step 2 of 3: Metadata selection'),
|
_(u'step 2 of 3: Metadata selection'),
|
||||||
_(u'step 3 of 3: Document metadata'),
|
_(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):
|
return self.initial_dict.get(step, {})
|
||||||
context = {
|
|
||||||
'step_title': self.extra_context['step_titles'][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_label': _(u'Next step'),
|
||||||
'submit_icon_famfam': 'arrow_right',
|
'submit_icon_famfam': 'arrow_right',
|
||||||
}
|
})
|
||||||
return super(DocumentCreateWizard, self).render_template(
|
return context
|
||||||
request, form, previous_fields, step, context
|
|
||||||
)
|
|
||||||
|
|
||||||
def parse_params(self, request, *args, **kwargs):
|
def done(self, form_list):
|
||||||
self.extra_context = {'step_titles': self.step_titles}
|
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):
|
try:
|
||||||
if isinstance(form, DocumentTypeSelectForm):
|
for identifier, metadata in enumerate(self.get_cleaned_data_for_step('2')):
|
||||||
self.document_type = form.cleaned_data['document_type']
|
query_dict['metadata%s_id' % identifier] = metadata['id']
|
||||||
self.initial = {1: {'document_type': self.document_type}}
|
query_dict['metadata%s_value' % identifier] = metadata['value']
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
|
||||||
if isinstance(form, MetadataSelectionForm):
|
url = '?'.join([reverse('upload_interactive'), urlencode(query_dict, doseq=True)])
|
||||||
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)])
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|||||||
Reference in New Issue
Block a user