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): | 
