Skip to content

Commit

Permalink
Backported django.contrib.formtools.wizard. Compat. with Django 1.4+
Browse files Browse the repository at this point in the history
  • Loading branch information
stephrdev committed Jun 5, 2011
1 parent 9c82061 commit d04f8d7
Show file tree
Hide file tree
Showing 30 changed files with 1,419 additions and 1,277 deletions.
2 changes: 1 addition & 1 deletion AUTHORS
@@ -1 +1 @@
Stephan Jaekel <steph@rdev.info>
Stephan Jaekel <steph@rdev.info>Jannis Leidel <jannis@leidel.info>
Expand Down
Empty file removed formwizard/contrib/__init__.py
Empty file.
7 changes: 0 additions & 7 deletions formwizard/contrib/forms.py

This file was deleted.

654 changes: 3 additions & 651 deletions formwizard/forms.py

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions formwizard/models.py
@@ -0,0 +1 @@
# empty models file.
20 changes: 8 additions & 12 deletions formwizard/storage/__init__.py
@@ -1,25 +1,21 @@
from django.core.exceptions import ImproperlyConfigured
from django.utils.importlib import import_module

try:
from importlib import import_module
except ImportError:
from django.utils.importlib import import_module
from formwizard.storage.base import BaseStorage
from formwizard.storage.exceptions import (MissingStorageModule,
MissingStorageClass, NoFileStorageConfigured)

class MissingStorageModuleException(ImproperlyConfigured):
pass

class MissingStorageClassException(ImproperlyConfigured):
pass

def get_storage(path, *args, **kwargs):
i = path.rfind('.')
module, attr = path[:i], path[i+1:]
try:
mod = import_module(module)
except ImportError, e:
raise MissingStorageModuleException('Error loading storage %s: "%s"' % (module, e))
raise MissingStorageModule(
'Error loading storage %s: "%s"' % (module, e))
try:
storage_class = getattr(mod, attr)
except AttributeError:
raise MissingStorageClassException('Module "%s" does not define a storage named "%s"' % (module, attr))
raise MissingStorageClass(
'Module "%s" does not define a storage named "%s"' % (module, attr))
return storage_class(*args, **kwargs)
99 changes: 77 additions & 22 deletions formwizard/storage/base.py
@@ -1,39 +1,94 @@
class NoFileStorageException(Exception):
pass
from django.core.files.uploadedfile import UploadedFile
from django.utils.functional import lazy_property
from django.utils.encoding import smart_str

from formwizard.storage.exceptions import NoFileStorageConfigured


class BaseStorage(object):
def __init__(self, prefix):
self.prefix = 'formwizard_%s' % prefix
step_key = 'step'
step_data_key = 'step_data'
step_files_key = 'step_files'
extra_data_key = 'extra_data'

def get_current_step(self):
raise NotImplementedError()
def __init__(self, prefix, request=None, file_storage=None):
self.prefix = 'wizard_%s' % prefix
self.request = request
self.file_storage = file_storage

def set_current_step(self, step):
raise NotImplementedError()
def init_data(self):
self.data = {
self.step_key: None,
self.step_data_key: {},
self.step_files_key: {},
self.extra_data_key: {},
}

def get_step_data(self, step):
raise NotImplementedError()
def reset(self):
self.init_data()

def _get_current_step(self):
return self.data[self.step_key]

def _set_current_step(self, step):
self.data[self.step_key] = step

current_step = lazy_property(_get_current_step, _set_current_step)

def _get_extra_data(self):
return self.data[self.extra_data_key] or {}

def get_current_step_data(self):
raise NotImplementedError()
def _set_extra_data(self, extra_data):
self.data[self.extra_data_key] = extra_data

extra_data = lazy_property(_get_extra_data, _set_extra_data)

def get_step_data(self, step):
return self.data[self.step_data_key].get(step, None)

def set_step_data(self, step, cleaned_data):
raise NotImplementedError()
self.data[self.step_data_key][step] = cleaned_data

@property
def current_step_data(self):
return self.get_step_data(self.current_step)

def get_step_files(self, step):
raise NotImplementedError()
wizard_files = self.data[self.step_files_key].get(step, {})

if wizard_files and not self.file_storage:
raise NoFileStorageConfigured

files = {}
for field, field_dict in wizard_files.iteritems():
field_dict = dict((smart_str(k), v)
for k, v in field_dict.iteritems())
tmp_name = field_dict.pop('tmp_name')
files[field] = UploadedFile(
file=self.file_storage.open(tmp_name), **field_dict)
return files or None

def set_step_files(self, step, files):
raise NotImplementedError()
if files and not self.file_storage:
raise NoFileStorageConfigured

def get_extra_context_data(self):
raise NotImplementedError()
if step not in self.data[self.step_files_key]:
self.data[self.step_files_key][step] = {}

def set_extra_context_data(self, extra_context):
raise NotImplementedError()
for field, field_file in (files or {}).iteritems():
tmp_filename = self.file_storage.save(field_file.name, field_file)
file_dict = {
'tmp_name': tmp_filename,
'name': field_file.name,
'content_type': field_file.content_type,
'size': field_file.size,
'charset': field_file.charset
}
self.data[self.step_files_key][step][field] = file_dict

def reset(self):
raise NotImplementedError()
@property
def current_step_files(self):
return self.get_step_files(self.current_step)

def update_response(self, response):
raise NotImplementedError()
pass
139 changes: 21 additions & 118 deletions formwizard/storage/cookie.py
@@ -1,129 +1,32 @@
import hmac

from django.conf import settings
from django.core.exceptions import SuspiciousOperation
from django.utils.hashcompat import sha_constructor
from django.core.signing import BadSignature
from django.utils import simplejson as json
from formwizard.storage.base import BaseStorage, NoFileStorageException
from django.core.files.uploadedfile import UploadedFile
from django.core.files import File

sha_hmac = sha_constructor

class CookieStorage(BaseStorage):
step_cookie_key = 'step'
step_data_cookie_key = 'step_data'
step_files_cookie_key = 'step_files'
extra_context_cookie_key = 'extra_context'

def __init__(self, prefix, request, file_storage, *args, **kwargs):
super(CookieStorage, self).__init__(prefix)
self.file_storage = file_storage
self.request = request
self.cookie_data = self.load_cookie_data()
if self.cookie_data is None:
self.init_storage()

def init_storage(self):
self.cookie_data = {
self.step_cookie_key: None,
self.step_data_cookie_key: {},
self.step_files_cookie_key: {},
self.extra_context_cookie_key: {},
}
return True

def get_current_step(self):
return self.cookie_data[self.step_cookie_key]

def set_current_step(self, step):
self.cookie_data[self.step_cookie_key] = step
return True

def get_step_data(self, step):
return self.cookie_data[self.step_data_cookie_key].get(step, None)

def get_current_step_data(self):
return self.get_step_data(self.get_current_step())

def set_step_data(self, step, cleaned_data):
self.cookie_data[self.step_data_cookie_key][step] = cleaned_data
return True


def set_step_files(self, step, files):
if files and not self.file_storage:
raise NoFileStorageException

if not self.cookie_data[self.step_files_cookie_key].has_key(step):
self.cookie_data[self.step_files_cookie_key][step] = {}

for field, field_file in (files or {}).items():
tmp_filename = self.file_storage.save(field_file.name, field_file)
file_dict = {
'tmp_name': tmp_filename,
'name': field_file.name,
'content_type': field_file.content_type,
'size': field_file.size,
'charset': field_file.charset
}
self.cookie_data[self.step_files_cookie_key][step][field] = file_dict
from formwizard import storage

return True

def get_current_step_files(self):
return self.get_step_files(self.get_current_step())
class CookieStorage(storage.BaseStorage):
encoder = json.JSONEncoder(separators=(',', ':'))

def get_step_files(self, step):
session_files = self.cookie_data[self.step_files_cookie_key].get(step, {})
def __init__(self, *args, **kwargs):
super(CookieStorage, self).__init__(*args, **kwargs)
self.data = self.load_data()
if self.data is None:
self.init_data()

if session_files and not self.file_storage:
raise NoFileStorageException

files = {}
for field, field_dict in session_files.items():
files[field] = UploadedFile(
file=self.file_storage.open(field_dict['tmp_name']),
name=field_dict['name'],
content_type=field_dict['content_type'],
size=field_dict['size'],
charset=field_dict['charset'],
)
return files or None

def get_extra_context_data(self):
return self.cookie_data[self.extra_context_cookie_key] or {}

def set_extra_context_data(self, extra_context):
self.cookie_data[self.extra_context_cookie_key] = extra_context
return True

def reset(self):
return self.init_storage()
def load_data(self):
try:
data = self.request.get_signed_cookie(self.prefix)
except KeyError:
data = None
except BadSignature:
raise SuspiciousOperation('FormWizard cookie manipulated')
if data is None:
return None
return json.loads(data, cls=json.JSONDecoder)

def update_response(self, response):
if len(self.cookie_data) > 0:
response.set_cookie(self.prefix, self.create_cookie_data(self.cookie_data))
if self.data:
response.set_signed_cookie(self.prefix, self.encoder.encode(self.data))
else:
response.delete_cookie(self.prefix)
return response

def load_cookie_data(self):
data = self.request.COOKIES.get(self.prefix, None)
if data is None:
return None

bits = data.split('$', 1)
if len(bits) == 2:
if bits[0] == self.get_cookie_hash(bits[1]):
return json.loads(bits[1], cls=json.JSONDecoder)

raise SuspiciousOperation('FormWizard cookie manipulated')

def get_cookie_hash(self, data):
return hmac.new('%s$%s' % (settings.SECRET_KEY, self.prefix), data, sha_hmac).hexdigest()

def create_cookie_data(self, data):
encoder = json.JSONEncoder(separators=(',', ':'))
encoded_data = encoder.encode(data)
return '%s$%s' % (self.get_cookie_hash(encoded_data), encoded_data)
10 changes: 10 additions & 0 deletions formwizard/storage/exceptions.py
@@ -0,0 +1,10 @@
from django.core.exceptions import ImproperlyConfigured

class MissingStorageModule(ImproperlyConfigured):
pass

class MissingStorageClass(ImproperlyConfigured):
pass

class NoFileStorageConfigured(ImproperlyConfigured):
pass

0 comments on commit d04f8d7

Please sign in to comment.