diff options
Diffstat (limited to 'ishtar_common/wizards.py')
-rw-r--r-- | ishtar_common/wizards.py | 121 |
1 files changed, 73 insertions, 48 deletions
diff --git a/ishtar_common/wizards.py b/ishtar_common/wizards.py index c5158dfcd..f522188a8 100644 --- a/ishtar_common/wizards.py +++ b/ishtar_common/wizards.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -# Copyright (C) 2010-2016 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet> +# Copyright (C) 2010-2017 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet> # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -22,24 +22,27 @@ import logging # from functools import wraps from django.conf import settings -from django.contrib.formtools.wizard.views import NamedUrlWizardView, \ - normalize_name, get_storage, StepsHelper +from formtools.wizard.views import NamedUrlWizardView, normalize_name, \ + get_storage, StepsHelper + from django.contrib.sites.models import Site from django.core.exceptions import ObjectDoesNotExist from django.core.files.images import ImageFile from django.core.files.storage import default_storage from django.core.mail import send_mail -from django.db.models.fields.files import FileField +from django.db.models.fields.files import FileField, ImageFieldFile from django.db.models.fields.related import ManyToManyField from django.db.models.fields import NOT_PROVIDED from django.http import HttpResponseRedirect from django.forms import ValidationError -from django.shortcuts import render_to_response, redirect -from django.template import Context, RequestContext, loader +from django.shortcuts import redirect, render +from django.template import loader from django.utils.datastructures import MultiValueDict as BaseMultiValueDict from django.utils.translation import ugettext_lazy as _ -import models + +from ishtar_common import models +from ishtar_common.utils import get_all_field_names logger = logging.getLogger(__name__) @@ -127,8 +130,7 @@ class Wizard(NamedUrlWizardView): label = '' translated_keys = [] modification = None # True when the wizard modify an item - storage_name = \ - 'django.contrib.formtools.wizard.storage.session.SessionStorage' + storage_name = 'formtools.wizard.storage.session.SessionStorage' wizard_done_template = 'ishtar/wizard/wizard_done.html' wizard_done_window = '' wizard_confirm = 'ishtar/wizard/confirm_wizard.html' @@ -276,6 +278,7 @@ class Wizard(NamedUrlWizardView): # simulate a non empty data for form that might be # valid when empty prefixed_values['__non_empty_data'] = '' + self.prepare_serialization(prefixed_values) storage.set_step_data(next_step, prefixed_values) if step == next_step: current_step_passed = True @@ -357,7 +360,7 @@ class Wizard(NamedUrlWizardView): if form_datas: form_datas.append(("", "", "spacer")) items = hasattr(base_form, 'fields') and \ - base_form.fields.keyOrder or cleaned_data.keys() + base_form.fields.keys() or cleaned_data.keys() for key in items: lbl = None if key.startswith('hidden_'): @@ -368,7 +371,7 @@ class Wizard(NamedUrlWizardView): if hasattr(base_form, 'associated_labels') \ and key in base_form.associated_labels: lbl = base_form.associated_labels[key] - if not lbl: + if not lbl or key not in cleaned_data: continue value = cleaned_data[key] if value is None or value == '': @@ -528,7 +531,7 @@ class Wizard(NamedUrlWizardView): for k in dct: if k.startswith('pk'): continue - if k not in obj.__class__._meta.get_all_field_names(): + if k not in get_all_field_names(obj.__class__): continue # False set to None for images and files if not k.endswith('_id') and ( @@ -608,7 +611,7 @@ class Wizard(NamedUrlWizardView): if 'pk' in dct: dct.pop('pk') # remove non relevant fields - all_field_names = self.get_saved_model()._meta.get_all_field_names() + all_field_names = get_all_field_names(self.get_saved_model()) for k in dct.copy(): if not (k.endswith('_id') and k[:-3] in all_field_names) \ and k not in all_field_names and \ @@ -715,19 +718,22 @@ class Wizard(NamedUrlWizardView): # check if there is no missing fields # should be managed normally in forms but... - if hasattr(model._meta, 'get_fields'): # django 1.8 - fields = model._meta.get_field() - else: - fields = model._meta.fields + fields = model._meta.get_fields() - has_problemetic_null = [ - (field.name, field.default == NOT_PROVIDED) - for field in fields + + has_problemetic_null = False + for field in fields: if (field.name not in value - or not value[field.name]) - and not field.null and not field.blank - and (not field.default - or field.default == NOT_PROVIDED)] + or not value[field.name]) \ + and (hasattr(field, 'null') + and not field.null) \ + and (hasattr(field, 'blank') + and not field.blank) \ + and (hasattr(field, 'default') + and (not field.default + or field.default == NOT_PROVIDED)): + has_problemetic_null = True + break if has_problemetic_null: continue @@ -739,7 +745,9 @@ class Wizard(NamedUrlWizardView): value.save() # force post_save # check that an item is not add multiple times (forged forms) if value not in related_model.all() and\ - hasattr(related_model, 'add'): + (not hasattr(related_model, 'through') or + not isinstance(value, related_model.through)): + # many to many and the value have been already managed related_model.add(value) # necessary to manage interaction between models like # material_index management for baseitems @@ -771,8 +779,7 @@ class Wizard(NamedUrlWizardView): wizard_done_window = unicode(self.wizard_done_window) if wizard_done_window: dct['wizard_done_window'] = wizard_done_window - res = render_to_response(self.wizard_done_template, dct, - context_instance=RequestContext(self.request)) + res = render(self.request, self.wizard_done_template, dct) return return_object and (obj, res) or res def get_deleted(self, keys): @@ -876,7 +883,7 @@ class Wizard(NamedUrlWizardView): frm = form.forms[0] if frm: # autofocus on first field - first_field = frm.fields[frm.fields.keyOrder[0]] + first_field = frm.fields[frm.fields.keys()[0]] attrs = first_field.widget.attrs attrs.update({'autofocus': "autofocus"}) first_field.widget.attrs = attrs @@ -984,6 +991,19 @@ class Wizard(NamedUrlWizardView): data[key] = value storage.set_step_data(form_key, data) + @classmethod + def prepare_serialization(cls, data): + """ + Image and file cannot be passed as object + """ + for k in data: + if isinstance(data[k], ImageFieldFile) \ + or isinstance(data[k], FileField): + try: + data[k] = data[k].path + except ValueError: + data[k] = None + def session_get_value(self, form_key, key, multi=False, multi_value=False): """Get the value of a specific form""" if not self.session_has_key(form_key, key, multi): @@ -1112,9 +1132,9 @@ class Wizard(NamedUrlWizardView): continue if hasattr(value, 'pk'): value = value.pk - if value in (True, False) or \ - isinstance(value, FileField) or \ - isinstance(value, ImageFile): + if value in (True, False) \ + or isinstance(value, ImageFieldFile) \ + or isinstance(value, FileField): initial[base_field] = value elif value is not None: initial[base_field] = unicode(value) @@ -1164,8 +1184,7 @@ class SearchWizard(NamedUrlWizardView): model = None label = '' modification = None # True when the wizard modify an item - storage_name = \ - 'django.contrib.formtools.wizard.storage.session.SessionStorage' + storage_name = 'formtools.wizard.storage.session.SessionStorage' def get_wizard_name(self): """ @@ -1241,9 +1260,8 @@ class DeletionWizard(Wizard): obj.delete() except ObjectDoesNotExist: pass - return render_to_response( - 'ishtar/wizard/wizard_delete_done.html', {}, - context_instance=RequestContext(self.request)) + return render( + self.request, 'ishtar/wizard/wizard_delete_done.html', {}) class ClosingWizard(Wizard): @@ -1294,9 +1312,8 @@ class ClosingWizard(Wizard): and hasattr(obj, 'end_date'): obj.end_date = form.cleaned_data['end_date'] obj.save() - return render_to_response( - 'ishtar/wizard/wizard_closing_done.html', {}, - context_instance=RequestContext(self.request)) + return render( + self.request, 'ishtar/wizard/wizard_closing_done.html', {}) class PersonWizard(Wizard): @@ -1377,17 +1394,24 @@ class AccountWizard(Wizard): if key.startswith('hidden_password'): dct['password'] = dct.pop(key) try: - account = models.IshtarUser.objects.get(person=person) + account = models.IshtarUser.objects.get(person=person).user_ptr account.username = dct['username'] account.email = dct['email'] except ObjectDoesNotExist: now = datetime.datetime.now() - account = models.IshtarUser( - person=person, username=dct['username'], email=dct['email'], + account = models.User.objects.create( + username=dct['username'], email=dct['email'], first_name=person.surname or '***', last_name=person.name or '***', is_staff=False, is_active=True, is_superuser=False, - last_login=now, date_joined=now) + last_login=now, date_joined=now + ) + ishtaruser = account.ishtaruser + old_person_pk = ishtaruser.person.pk + ishtaruser.person = person + ishtaruser.save() + models.Person.objects.get(pk=old_person_pk).delete() + if dct['password']: account.set_password(dct['password']) account.save() @@ -1398,20 +1422,21 @@ class AccountWizard(Wizard): app_name = site and ("Ishtar - " + site.name) \ or "Ishtar" - context = Context({ + context = { 'login': dct['username'], 'password': dct['password'], 'app_name': app_name, 'site': site and site.domain or "" - }) + } t = loader.get_template('account_activation_email.txt') - msg = t.render(context) + msg = t.render(context, self.request) subject = _(u"[%(app_name)s] Account creation/modification") % { "app_name": app_name} send_mail(subject, msg, settings.ADMINS[0][1], [dct['email']], fail_silently=True) - res = render_to_response('ishtar/wizard/wizard_done.html', {}, - context_instance=RequestContext(self.request)) + res = render( + self.request, 'ishtar/wizard/wizard_done.html', {}, + ) return res def get_form_kwargs(self, step=None): |