summaryrefslogtreecommitdiff
path: root/ishtar/ishtar_base/views.py
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@peacefrogs.net>2012-10-18 17:49:57 +0200
committerÉtienne Loks <etienne.loks@peacefrogs.net>2012-10-18 17:51:30 +0200
commit7d2aa560ba859ebb593d34b062bf1faf09c8724c (patch)
tree4136673563f802d6de992512e3c4adde86ef2a4e /ishtar/ishtar_base/views.py
parent615457617e65019e0ce39b585f4eeb41b17ba61a (diff)
downloadIshtar-7d2aa560ba859ebb593d34b062bf1faf09c8724c.tar.bz2
Ishtar-7d2aa560ba859ebb593d34b062bf1faf09c8724c.zip
Djangoization - Major refactoring (step 1)
Diffstat (limited to 'ishtar/ishtar_base/views.py')
-rw-r--r--ishtar/ishtar_base/views.py1333
1 files changed, 0 insertions, 1333 deletions
diff --git a/ishtar/ishtar_base/views.py b/ishtar/ishtar_base/views.py
deleted file mode 100644
index 4a7f276fb..000000000
--- a/ishtar/ishtar_base/views.py
+++ /dev/null
@@ -1,1333 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-# Copyright (C) 2010-2011 É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
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-# See the file COPYING for details.
-
-try:
- import tidy
-except:
- from tidylib import tidy_document as tidy
-
-import re
-import csv
-import json
-import datetime
-import optparse
-import cStringIO as StringIO
-from tempfile import NamedTemporaryFile
-import ho.pisa as pisa
-
-from django.contrib.formtools.wizard.views import NamedUrlWizardView
-from django.core import serializers
-from django.core.exceptions import ObjectDoesNotExist
-from django.core.urlresolvers import reverse, NoReverseMatch
-from django.db.models import Q
-from django.http import HttpResponse, Http404
-from django.shortcuts import render_to_response, redirect
-from django.template import RequestContext, loader
-from django.template.defaultfilters import slugify
-from django.utils.translation import ugettext, ugettext_lazy as _
-
-from ishtar import settings
-if settings.XHTML2ODT_PATH:
- import sys
- sys.path.append(settings.XHTML2ODT_PATH)
- from xhtml2odt import xhtml2odt
-
-from menus import menu
-import forms_main as ishtar_forms
-
-from ishtar.ishtar_base.forms import FinalForm
-from ishtar.ishtar_base.forms_common import PersonForm
-import models
-
-CSV_OPTIONS = {'delimiter':';', 'quotechar':'"', 'quoting':csv.QUOTE_ALL}
-ENCODING = settings.ENCODING or 'utf-8'
-
-def index(request):
- """
- Main page
- """
- dct = {}
- return render_to_response('index.html', dct,
- context_instance=RequestContext(request))
-
-class Wizard(NamedUrlWizardView):
- model = None
- modification = None # True when the wizard modify an item
- storage_name = 'django.contrib.formtools.wizard.storage.session.SessionStorage'
-
- @staticmethod
- def _check_right(step, condition=True):
- '''Return a method to check the right for a specific step'''
- """
- def check_right(self, request, storage):
- cond = condition
- if callable(condition):
- cond = condition(self, request, storage)
- if not cond:
- return False
- person_type = request.user.ishtaruser.person.person_type
- if person_type.txt_idx == 'administrator':
- return True
- if person_type.rights.filter(url_name=step).count():
- return True"""
- def check_right(self):
- cond = condition
- if callable(condition):
- cond = condition(self)
- if not cond:
- return False
- person_type = self.request.user.ishtaruser.person.person_type
- if person_type.txt_idx == 'administrator':
- return True
- if person_type.rights.filter(url_name=step).count():
- return True
- return check_right
-
- def __init__(self, *args, **kwargs):
- """Check right for each step of the wizard"""
- super(Wizard, self).__init__(*args, **kwargs)
- for form_key in self.form_list.keys()[:-1]:
- condition = True
- if form_key in self.condition_dict:
- condition = self.condition_dict.get(form_key, True)
- cond = self._check_right(form_key, condition)
- self.condition_dict[form_key] = cond
- """
- for form_key in self.form_list.keys()[:-1]:
- condition = True
- if form_key in self.condition_list:
- condition = self.condition_list.get(form_key, True)
- cond = self._check_right(form_key, condition)
- self.condition_list[form_key] = cond"""
-
- def get_wizard_name(self):
- """As the class name can interfere when reused, use the url_name"""
- return self.url_name
-
- def get_template_names(self):
- templates = ['ishtar/wizard/default_wizard.html']
- current_step = self.steps.current
- if current_step == self.steps.last:
- templates = ['ishtar/wizard/confirm_wizard.html'] + templates
- return templates
-
- def get_context_data(self, form, **kwargs):
- """Add previous, next and current steps to manage the wizard path"""
- context = super(Wizard, self).get_context_data(form)
- step = self.steps.first
- current_step = self.steps.current
- context.update({'current_step':self.form_list[current_step]})
- if step == current_step:
- return context
- previous_steps, next_steps, previous_step_counter = [], [], 0
- while step:
- if step == current_step:
- break
- previous_steps.append(self.form_list[step])
- step = self.steps.next
- previous_step_counter += 1
- context.update({'previous_steps':previous_steps,
- 'previous_step_counter':previous_step_counter})
- # if modification: show the next steps
- if self.modification:
- next_step = step
- while next_step:
- # check if the form is initialized otherwise initialize it
- if not storage.get_step_data(next_step):
- values = self.get_form_initial(request, storage, next_step)
- prefixed_values = {}
- if not isinstance(values, list):
- for key in values:
- form_key = next_step + '-' + key
- prefixed_values[form_key] = values[key]
- else:
- for formset_idx, v in enumerate(values):
- prefix = u"-%d-" % formset_idx
- for key in v:
- form_key = next_step + prefix + key
- prefixed_values[form_key] = v[key]
- storage.set_step_data(next_step, prefixed_values)
- if step != next_step: # if not current step
- next_steps.append(self.form_list[next_step])
- next_step = self.get_next_step(request, storage, next_step)
- context.update({'next_steps':next_steps})
- # not last step: validation
- if current_step != self.steps.last:
- return context
- final_form_list = []
- for form_key in self.get_form_list().keys():
- form_obj = self.get_form(step=form_key,
- data=self.storage.get_step_data(form_key),
- files=self.storage.get_step_files(form_key))
- form_obj.is_valid()
- final_form_list.append(form_obj)
- last_form = final_form_list[-1]
- context.update({'datas':self.get_formated_datas(final_form_list)})
- if hasattr(last_form, 'confirm_msg'):
- context.update({'confirm_msg':last_form.confirm_msg})
- if hasattr(last_form, 'confirm_end_msg'):
- context.update({'confirm_end_msg':last_form.confirm_end_msg})
- return context
-
- def get_formated_datas(self, forms):
- """Get the data to present in the last page"""
- datas = []
- for form in forms:
- form_datas = []
- base_form = hasattr(form, 'forms') and form.forms[0] or form
- associated_models = hasattr(base_form, 'associated_models') and \
- base_form.associated_models or {}
- if not hasattr(form, 'cleaned_data') and hasattr(form, 'forms'):
- cleaned_datas = [frm.cleaned_data for frm in form.forms
- if frm.is_valid()]
- if not cleaned_datas:
- continue
- elif not hasattr(form, 'cleaned_data'):
- continue
- else:
- cleaned_datas = type(form.cleaned_data) == list and \
- form.cleaned_data \
- or [form.cleaned_data]
- for cleaned_data in cleaned_datas:
- if not cleaned_data:
- continue
- if form_datas:
- form_datas.append(("", "", "spacer"))
- items = hasattr(base_form, 'fields') and \
- base_form.fields.keyOrder or cleaned_data.keys()
- for key in items:
- lbl = None
- if key.startswith('hidden_'):
- continue
- if hasattr(base_form, 'fields') and key in base_form.fields:
- lbl = base_form.fields[key].label
- if hasattr(base_form, 'associated_labels') \
- and key in base_form.associated_labels:
- lbl = base_form.associated_labels[key]
- if not lbl:
- continue
- value = cleaned_data[key]
- if not value and value != False:
- continue
- if type(value) == bool:
- if value == True:
- value = _(u"Yes")
- elif value == False:
- value = _(u"No")
- elif key in associated_models:
- values = []
- if "," in unicode(value):
- values = unicode(value).split(",")
- else:
- values = [value]
- rendered_values = []
- for val in values:
- item = associated_models[key].objects.get(pk=val)
- if hasattr(item, 'short_label'):
- value = item.short_label()
- else:
- value = unicode(item)
- rendered_values.append(value)
- value = u" ; ".join(rendered_values)
- form_datas.append((lbl, value, ''))
- if form_datas:
- datas.append((form.form_label, form_datas))
- return datas
-
- def get_extra_model(self, dct, form_list):
- dct['history_modifier'] = self.request.user
- return dct
-
- def done(self, form_list, return_object=False, **kwargs):
- """Save to the model"""
- dct, m2m, whole_associated_models = {}, [], []
- for form in form_list:
- if not form.is_valid():
- return self.render(form)
- base_form = hasattr(form, 'forms') and form.forms[0] or form
- associated_models = hasattr(base_form, 'associated_models') and \
- base_form.associated_models or {}
- if hasattr(form, 'forms'):
- multi = False
- if form.forms:
- frm = form.forms[0]
- if hasattr(frm, 'base_model') and frm.base_model:
- whole_associated_models.append(frm.base_model)
- else:
- whole_associated_models += associated_models.keys()
- fields = frm.fields.copy()
- if 'DELETE' in fields:
- fields.pop('DELETE')
- multi = len(fields) > 1
- if multi:
- assert hasattr(frm, 'base_model'), \
- u"Must define a base_model for " + unicode(frm.__class__)
- for frm in form.forms:
- if not frm.is_valid():
- continue
- vals = {}
- if "DELETE" in frm.cleaned_data:
- if frm.cleaned_data["DELETE"]:
- continue
- frm.cleaned_data.pop('DELETE')
- for key in frm.cleaned_data:
- value = frm.cleaned_data[key]
- if not value and value != False:
- continue
- if key in associated_models:
- value = associated_models[key].objects.get(pk=value)
- if multi:
- vals[key] = value
- else:
- m2m.append((key, value))
- if multi and vals:
- m2m.append((frm.base_model, vals))
- elif type(form.cleaned_data) == dict:
- for key in form.cleaned_data:
- if key.startswith('hidden_'):
- continue
- value = form.cleaned_data[key]
- if key in associated_models:
- if value:
- model = associated_models[key]
- if isinstance(value, unicode) \
- or isinstance(value, str) and "," in value:
- value = value.split(",")
- if isinstance(value, list) \
- or isinstance(value, tuple):
- value = [model.objects.get(pk=val)
- for val in value if val]
- if len(value) == 1:
- value = value[0]
- else:
- value = model.objects.get(pk=value)
- else:
- value = None
- dct[key] = value
- return self.save_model(dct, m2m, whole_associated_models, form_list,
- return_object)
-
- def get_saved_model(self):
- """Permit a distinguo when saved model is not the base selected model"""
- return self.model
-
- def get_current_saved_object(self):
- """Permit a distinguo when saved model is not the base selected model"""
- return self.get_current_object()
-
- def save_model(self, dct, m2m, whole_associated_models, form_list,
- return_object):
- dct = self.get_extra_model(dct, form_list)
- obj = self.get_current_saved_object()
- # manage dependant items
- other_objs = {}
- for k in dct.keys():
- if '__' not in k:
- continue
- vals = k.split('__')
- assert len(vals) == 2, "Only one level of dependant item is managed"
- dependant_item, key = vals
- if dependant_item not in other_objs:
- other_objs[dependant_item] = {}
- other_objs[dependant_item][key] = dct.pop(k)
- if obj:
- for k in dct:
- if k.startswith('pk'):
- continue
- setattr(obj, k, dct[k])
- try:
- obj.full_clean()
- except forms.ValidationError, msg:
- return self.render(form_list[-1])
- for dependant_item in other_objs:
- c_item = getattr(obj, dependant_item)
- # manage ManyToMany if only one associated
- if hasattr(c_item, "all"):
- c_items = c_item.all()
- if len(c_items) != 1:
- continue
- c_item = c_items[0]
- if c_item:
- # to check #
- for k in other_objs[dependant_item]:
- setattr(c_item, k, other_objs[dependant_item][k])
- c_item.save()
- else:
- m = getattr(self.model, dependant_item)
- if hasattr(m, 'related'):
- c_item = m.related.model(**other_objs[dependant_item])
- setattr(obj, dependant_item, c_item)
- obj.save()
- obj.save()
- else:
- adds = {}
- for dependant_item in other_objs:
- m = getattr(self.model, dependant_item)
- model = m.field.rel.to
- c_dct = other_objs[dependant_item].copy()
- if issubclass(model, models.BaseHistorizedItem):
- c_dct['history_modifier'] = self.request.user
- c_item = model(**c_dct)
- c_item.save()
- if hasattr(m, 'through'):
- adds[dependant_item] = c_item
- elif hasattr(m, 'field'):
- dct[dependant_item] = c_item
- if 'pk' in dct:
- dct.pop('pk')
- obj = self.get_saved_model()(**dct)
- try:
- obj.full_clean()
- except forms.ValidationError, msg:
- return self.render(form_list[-1])
- obj.save()
- for k in adds:
- getattr(obj, k).add(adds[k])
- # necessary to manage interaction between models like
- # material_index management for baseitems
- obj.save()
- m2m_items = {}
- for model in whole_associated_models:
- getattr(obj, model+'s').clear()
- for key, value in m2m:
- if key not in m2m_items:
- if type(key) == dict:
- vals = []
- for item in getattr(obj, key+'s').all():
- v = {}
- for k in value.keys():
- v[k] = getattr(item, k)
- vals.append(v)
- m2m_items[key] = vals
- else:
- m2m_items[key] = getattr(obj, key+'s').all()
- if value not in m2m_items[key]:
- if type(value) == dict:
- model = getattr(obj, key+'s').model
- if issubclass(model, models.BaseHistorizedItem):
- value['history_modifier'] = self.request.user
- value = model.objects.create(**value)
- value.save()
- getattr(obj, key+'s').add(value)
- # necessary to manage interaction between models like
- # material_index management for baseitems
- obj.save()
- res = render_to_response('wizard_done.html', {},
- context_instance=RequestContext(self.request))
- return return_object and (obj, res) or res
-
- def get_deleted(self, keys):
- """Get the deleted and non-deleted items in formsets"""
- not_to_delete, to_delete = set(), set()
- for key in keys:
- items = key.split('-')
- if len(items) < 2 or items[-2] in to_delete:
- continue
- idx = items[-2]
- try:
- int(idx)
- except:
- continue
- if items[-1] == u'DELETE':
- to_delete.add(idx)
- if idx in not_to_delete:
- not_to_delete.remove(idx)
- elif idx not in not_to_delete:
- not_to_delete.add(idx)
- return (to_delete, not_to_delete)
-
- def get_form(self, step=None, data=None, files=None):
- """Manage formset"""
- request = self.request
- storage = self.storage
- if data:
- data = data.copy()
- if not step:
- step = self.steps.current
- form = self.get_form_list()[step]
- if hasattr(form, 'management_form'):
- # manage deletion
- to_delete, not_to_delete = self.get_deleted(data.keys())
- # raz deleted fields
- for key in data.keys():
- items = key.split('-')
- if len(items) < 2 or items[-2] not in to_delete:
- continue
- data.pop(key)
- if to_delete:
- # reorganize
- for idx, number in enumerate(sorted(not_to_delete)):
- idx = unicode(idx)
- if idx == number:
- continue
- for key in data.keys():
- items = key.split('-')
- if len(items) > 2 and number == items[-2]:
- items[-2] = unicode(idx)
- k = u'-'.join(items)
- data[k] = data.pop(key)[0]
- # get a form key
- base_key = form.form.base_fields.keys()[0]
- init = self.get_form_initial(request, storage, step)
- total_field = len([key for key in data.keys()
- if base_key in key.split('-')
- and data[key]])
- if init and not to_delete:
- total_field = max((total_field, len(init)))
- data[step + u'-INITIAL_FORMS'] = unicode(total_field)
- data[step + u'-TOTAL_FORMS'] = unicode(total_field + 1)
- data = data or None
- form = super(Wizard, self).get_form(step, data, files)
- return form
-
- def render_next_step(self, form, **kwargs):
- """
- Manage:
- - modify or delete button in formset: next step = current step
- - validate and end: nextstep = last step
- """
- request = self.request
- if request.POST.has_key('formset_modify') \
- and request.POST['formset_modify'] \
- or [key for key in request.POST.keys()
- if key.endswith('DELETE') and request.POST[key]]:
- return self.render(form)
- elif request.POST.has_key('validate_and_end') \
- and request.POST['validate_and_end']:
- last_step = self.steps.last
- new_form = self.get_form(last_step,
- data=self.storage.get_step_data(last_step),
- files=self.storage.get_step_files(last_step))
- self.storage.current_step = last_step
- return self.render(new_form)
- return super(Wizard, self).render_next_step(form, **kwargs)
-
- def post(self, *args, **kwargs):
- """Convert numerical step number to step name"""
- request = self.request
- post_data = request.POST.copy()
- if request.POST.has_key('form_prev_step'):
- try:
- step_number = int(request.POST['form_prev_step'])
- post_data['wizard_goto_step'] = self.get_form_list().keys(
- )[step_number]
- except ValueError:
- pass
- request.POST = post_data
- return super(Wizard, self).post(*args, **kwargs)
-
- @classmethod
- def session_has_key(cls, request, storage, form_key, key=None, multi=None):
- """Check if the session has value of a specific form and (if provided)
- of a key
- """
- test = storage.prefix in request.session \
- and 'step_data' in request.session[storage.prefix] \
- and form_key in request.session[storage.prefix]['step_data']
- if not key or not test:
- return test
- key = key.startswith(form_key) and key or \
- not multi and form_key + '-' + key or \
- form_key + '-0-' + key #only check if the first field is available
- return key in request.session[storage.prefix]['step_data'][form_key]
-
- @classmethod
- def session_get_value(cls, request, storage, form_key, key, multi=False):
- """Get the value of a specific form"""
- if not cls.session_has_key(request, storage, form_key, key, multi):
- return
- if not multi:
- key = key.startswith(form_key) and key or form_key + '-' + key
- return request.session[storage.prefix]['step_data'][form_key][key]
- vals = []
- for k in request.session[storage.prefix]['step_data'][form_key]:
- if k.startswith(form_key) and k.endswith(key) and \
- request.session[storage.prefix]['step_data'][form_key][k]:
- vals.append(request.session[storage.prefix]['step_data']\
- [form_key][k])
- return vals
-
- def get_current_object(self):
- """Get the current object for an instancied wizard"""
- current_obj = None
- main_form_key = 'selec-' + self.url_name
- try:
- idx = int(self.session_get_value(self.request, self.storage,
- main_form_key, 'pk'))
- current_obj = self.model.objects.get(pk=idx)
- except(TypeError, ValueError, ObjectDoesNotExist):
- pass
- return current_obj
-
- def get_form_initial(self, step):
- current_obj = self.get_current_object()
- current_step = self.steps.current
- if step.startswith('selec-') and step in self.form_list \
- and 'pk' in self.form_list[step].associated_models:
- model_name = self.form_list[step].associated_models['pk'
- ].__name__.lower()
- if step == current_step:
- self.reset_wizard(request, storage)
- val = model_name in request.session and request.session[model_name]
- if val:
- return {'pk':val}
- elif current_obj:
- return self.get_instanced_init(current_obj, step)
- current_form = self.form_list[current_step]
- if hasattr(current_form, 'currents'):
- initial = {}
- for key in current_form.currents:
- model_name = current_form.currents[key].__name__.lower()
- val = model_name in request.session and \
- request.session[model_name]
- if val:
- initial[key] = val
- if initial:
- return initial
- return super(Wizard, self).get_form_initial(step)
-
- def get_instanced_init(self, obj, step=None):
- """Get initial data from an init"""
- current_step = step or self.steps.current
- c_form = self.form_list[current_step]
- # make the current object the default item for the session
- obj_name = obj.__class__.__name__.lower()
- # prefer a specialized name if available
- prefixes = self.storage.prefix.split('_')
- if len(prefixes) > 1 and prefixes[-2].startswith(obj_name):
- obj_name = prefixes[-2]
- self.request.session[obj_name] = unicode(obj.pk)
- initial = {}
- if self.request.POST or \
- (step in self.request.session[self.storage.prefix] and\
- self.request.session[self.storage.prefix]['step_data'][step]):
- return {}
- if hasattr(c_form, 'base_fields'):
- for base_field in c_form.base_fields.keys():
- fields = base_field.split('__')
- value = obj
- for field in fields:
- if not hasattr(value, field) or \
- getattr(value, field) == None:
- value = obj
- break
- value = getattr(value, field)
- if value == obj:
- continue
- if hasattr(value, 'pk'):
- value = value.pk
- if value in (True, False):
- initial[base_field] = value
- elif value != None:
- initial[base_field] = unicode(value)
- elif hasattr(c_form, 'management_form'):
- initial = []
- if hasattr(c_form.form, 'base_model'):
- key = c_form.form.base_model + 's'
- else:
- key = current_step.split('-')[0]
- if not hasattr(obj, key):
- return initial
- keys = c_form.form.base_fields.keys()
- for child_obj in getattr(obj, key).order_by('pk').all():
- if not keys:
- break
- vals = {}
- if len(keys) == 1:
- # only one field: must be the id of the object
- vals[keys[0]] = unicode(child_obj.pk)
- else:
- for field in keys:
- if hasattr(child_obj, field):
- value = getattr(child_obj, field)
- if hasattr(value, 'pk'):
- value = value.pk
- if value != None:
- vals[field] = unicode(value)
- if vals:
- initial.append(vals)
- return initial
-
-class PersonWizard(Wizard):
- model = models.Person
-
-person_creation_wizard = PersonWizard.as_view([
- ('identity-person_creation', PersonForm),
- ('final-person_creation', FinalForm)],
- url_name='person_creation_step',)
-
-
-def update_current_item(request):
- if not request.is_ajax() and not request.method == 'POST':
- raise Http404
- if 'value' in request.POST and 'item' in request.POST:
- request.session[request.POST['item']] = request.POST['value']
- return HttpResponse('ok')
-
-def check_permission(request, action_slug, obj_id=None):
- if action_slug not in menu.items:
- #! TODO
- return True
- if obj_id:
- return menu.items[action_slug].is_available(request.user, obj_id)
- return menu.items[action_slug].can_be_available(request.user)
-
-def autocomplete_person(request, person_type=None):
- person_types = request.user.ishtaruser.person.person_type
- if (not request.user.has_perm('ishtar_base.view_person', models.Person) and
- not request.user.has_perm('ishtar_base.view_own_person', models.Person)
- and not person_types.rights.filter(wizard__url_name='person_search'
- ).count()):
- return HttpResponse(mimetype='text/plain')
- if not request.GET.get('term'):
- return HttpResponse(mimetype='text/plain')
- q = request.GET.get('term')
- limit = request.GET.get('limit', 20)
- try:
- limit = int(limit)
- except ValueError:
- return HttpResponseBadRequest()
- query = Q()
- for q in q.split(' '):
- query = query & (Q(name__icontains=q) | Q(surname__icontains=q) | \
- Q(email__icontains=q))
- if person_type:
- try:
- typs = [int(tp) for tp in person_type.split('_') if tp]
- typ = models.PersonType.objects.filter(pk__in=typs).all()
- query = query & Q(person_type__in=typ)
- except (ValueError, ObjectDoesNotExist):
- pass
- limit = 20
- persons = models.Person.objects.filter(query)[:limit]
- data = json.dumps([{'id':person.pk, 'value':unicode(person)}
- for person in persons if person])
- return HttpResponse(data, mimetype='text/plain')
-
-def autocomplete_town(request):
- if not request.GET.get('term'):
- return HttpResponse(mimetype='text/plain')
- q = request.GET.get('term')
- query = Q()
- for q in q.split(' '):
- extra = Q(name__icontains=q)
- if settings.COUNTRY == 'fr':
- extra = (extra | Q(numero_insee__istartswith=q) | \
- Q(departement__label__istartswith=q))
- query = query & extra
- limit = 20
- towns = models.Town.objects.filter(query)[:limit]
- data = json.dumps([{'id':town.pk, 'value':unicode(town)}
- for town in towns])
- return HttpResponse(data, mimetype='text/plain')
-
-def autocomplete_file(request):
- person_types = request.user.ishtaruser.person.person_type
- if (not request.user.has_perm('ishtar_base.view_file', models.File) and \
- not request.user.has_perm('ishtar_base.view_own_file', models.File)
- and not person_types.rights.filter(wizard__url_name='file_search'
- ).count()):
- return HttpResponse(mimetype='text/plain')
- if not request.GET.get('term'):
- return HttpResponse(mimetype='text/plain')
- q = request.GET.get('term')
- query = Q()
- for q in q.split(' '):
- extra = Q(internal_reference__icontains=q) | \
- Q(towns__name__icontains=q)
- try:
- value = int(q)
- extra = extra | Q(year=q) | Q(numeric_reference=q)
- except ValueError:
- pass
- query = query & extra
- limit = 20
- files = models.File.objects.filter(query)[:limit]
- data = json.dumps([{'id':file.pk, 'value':unicode(file)}
- for file in files])
- return HttpResponse(data, mimetype='text/plain')
-
-from types import NoneType
-
-def format_val(val):
- if type(val) == NoneType:
- return u""
- if type(val) == bool:
- if val:
- return unicode(_(u"True"))
- else:
- return unicode(_(u"False"))
- return unicode(val)
-
-HIERARCHIC_LEVELS = 5
-HIERARCHIC_FIELDS = ['period', 'unit', 'material_type']
-PRIVATE_FIELDS = ('id', 'history_modifier', 'order')
-def get_item(model, func_name, default_name, extra_request_keys=[],
- base_request={}, bool_fields=[]):
- """
- Generic treatment of tables
- """
- def func(request, data_type='json', full=False, **dct):
- if 'type' in dct:
- data_type = dct.pop('type')
- if not data_type:
- data_type = 'json'
- fields = [model._meta.get_field_by_name(k)[0]
- for k in model._meta.get_all_field_names()]
- request_keys = dict([(field.name,
- field.name + (hasattr(field, 'rel') and field.rel and '__pk' or ''))
- for field in fields])
- request_keys.update(extra_request_keys)
- request_items = request.method == 'POST' and request.POST or request.GET
- dct = base_request.copy()
- try:
- old = 'old' in request_items and int(request_items['old'])
- except ValueError:
- return HttpResponse(None, mimetype='text/plain')
- for k in request_keys:
- q = request_items.get(k)
- if not q:
- continue
- dct[request_keys[k]] = q
- if not dct and 'submited' not in request_items:
- if default_name in request.session and \
- request.session[default_name]:
- dct = {"pk":request.session[default_name]}
- if (not dct or data_type == 'csv') and func_name in request.session:
- dct = request.session[func_name]
- else:
- request.session[func_name] = dct
- for k in bool_fields:
- if k in dct:
- if dct[k] == u"1":
- dct.pop(k)
- else:
- dct[k] = dct[k] == u"2" and True or False
-
- # manage hierarchic conditions
- or_reqs = []
- for req in dct.copy():
- for k_hr in HIERARCHIC_FIELDS:
- if req.endswith(k_hr + '__pk'):
- val = dct.pop(req)
- reqs = Q(**{req:val})
- req = req[:-2] + '__'
- for idx in xrange(HIERARCHIC_LEVELS):
- req = req[:-2] + 'parent__pk'
- q = Q(**{req:val})
- reqs = reqs | q
- or_reqs.append(reqs)
- break
- query = Q(**dct)
- for or_req in or_reqs:
- query = query & or_req
- items = model.objects.filter(query)
- q = request_items.get('sidx')
-
- # manage sort tables
- if q and q in request_keys:
- ks = request_keys[q]
- if type(ks) not in (list, tuple):
- ks = [ks]
- orders = []
- for k in ks:
- if k.endswith("__pk"):
- k = k[:-len("__pk")] + "__label"
- q = request_items.get('sord')
- sign = q and q == u'desc' and "-" or ''
- if '__' in k:
- k = k.split('__')[0]
- orders.append(sign+k)
- items = items.order_by(*orders)
-
- # pager management
- start, end = 0, None
- page_nb = 1
- try:
- row_nb = int(request_items.get('rows'))
- except (ValueError, TypeError):
- row_nb = None
- if row_nb:
- try:
- page_nb = int(request_items.get('page'))
- assert page_nb >= 1
- except (ValueError, AssertionError):
- pass
- start = (page_nb-1)*row_nb
- end = page_nb*row_nb
- items_nb = items.count()
- items = items[start:end]
-
- datas = []
- if old:
- items = [item.get_previous(old) for item in items]
- table_cols = full and [field.name for field in model._meta.fields
- if field.name not in PRIVATE_FIELDS] \
- or model.TABLE_COLS
- for item in items:
- data = [item.pk]
- for k in table_cols:
- vals = [item]
- for ky in k.split('.'):
- new_vals = []
- for val in vals:
- if hasattr(val, 'all'): # manage related objects
- val = list(val.all())
- for v in val:
- new_vals.append(getattr(v, ky))
- elif val:
- new_vals.append(getattr(val, ky))
- vals = new_vals
- if vals and hasattr(vals[0], 'all'): # manage last related objects
- new_vals = []
- for val in vals:
- new_vals += list(val.all())
- vals = new_vals
- data.append(", ".join([format_val(v) for v in vals]) or u"")
- datas.append(data)
- link_template = "<a href='#' onclick='load_window(\"%%s\")'>%s</a>" % \
- (unicode(_("Details")))
- if data_type == "json":
- rows = []
- for data in datas:
- try:
- lnk = link_template % reverse('show-'+default_name,
- args=[data[0], ''])
- except NoReverseMatch:
- lnk = ''
- res = {'id':data[0], 'link':lnk}
- for idx, value in enumerate(data[1:]):
- if value:
- res[table_cols[idx].split('.')[-1]] = value
- rows.append(res)
- data = json.dumps({
- "records":items_nb,
- "rows":rows,
- "page":page_nb,
- "total":items_nb/row_nb + 1,
- })
- return HttpResponse(data, mimetype='text/plain')
- elif data_type == "csv":
- response = HttpResponse(mimetype='text/csv')
- n = datetime.datetime.now()
- filename = u'%s_%s.csv' % (default_name,
- n.strftime('%Y%m%d-%H%M%S'))
- response['Content-Disposition'] = 'attachment; filename=%s'%filename
- writer = csv.writer(response, **CSV_OPTIONS)
- col_names = []
- for field_name in table_cols:
- try:
- field = model._meta.get_field(field_name)
- except:
- col_names.append(u"".encode(ENCODING))
- continue
- col_names.append(unicode(field.verbose_name).encode(ENCODING))
- writer.writerow(col_names)
- for data in datas:
- writer.writerow([val.encode(ENCODING) for val in data[1:]])
- return response
- return HttpResponse(None, mimetype='text/plain')
-
- return func
-
-def show_item(model, name):
- def func(request, pk, **dct):
- try:
- item = model.objects.get(pk=pk)
- except ObjectDoesNotExist:
- return HttpResponse(None)
- doc_type = 'type' in dct and dct.pop('type')
- date = 'date' in dct and dct.pop('date')
- dct['window_id'] = "%s-%d-%s" % (name, item.pk,
- datetime.datetime.now().strftime('%M%s'))
- if date:
- try:
- date = datetime.datetime.strptime(date, '%Y-%m-%dT%H:%M:%S.%f')
- item = item.get_previous(date=date)
- assert item != None
- except (ValueError, AssertionError):
- return HttpResponse(None, mimetype='text/plain')
- dct['previous'] = item._previous
- dct['next'] = item._next
- else:
- historized = item.history.all()
- if historized:
- item.history_date = historized[0].history_date
- if len(historized) > 1:
- dct['previous'] = historized[1].history_date
- dct['item'], dct['item_name'] = item, name
- context_instance = RequestContext(request)
- context_instance.update(dct)
- n = datetime.datetime.now()
- filename = u'%s_%s_%s' % (name, slugify(unicode(item)),
- n.strftime('%Y%m%d-%H%M%S'))
- if doc_type == "odt" and settings.XHTML2ODT_PATH and \
- settings.ODT_TEMPLATE:
- tpl = loader.get_template('sheet_%s.html' % name)
- content = tpl.render(context_instance)
- try:
- tidy_options = dict(output_xhtml=1, add_xml_decl=1, indent=1,
- tidy_mark=0, output_encoding='utf8', doctype='auto',
- wrap=0, char_encoding='utf8')
- html = str(tidy.parseString(content.encode('utf-8'),
- **tidy_options))
- html = html.replace("&nbsp;", "&#160;")
- html = re.sub('<pre([^>]*)>\n', '<pre\\1>', html)
-
- odt = NamedTemporaryFile()
- options = optparse.Values()
- options.with_network = True
- for k, v in (('input', ''),
- ('output', odt.name),
- ('template', settings.ODT_TEMPLATE),
- ('with_network', True),
- ('top_header_level', 1),
- ('img_width', '8cm'),
- ('img_height', '6cm'),
- ('verbose', False),
- ('replace_keyword', 'ODT-INSERT'),
- ('cut_start', 'ODT-CUT-START'),
- ('htmlid', None),
- ('url', "#")):
- setattr(options, k, v)
- odtfile = xhtml2odt.ODTFile(options)
- odtfile.open()
- odtfile.import_xhtml(html)
- odtfile = odtfile.save()
- except xhtml2odt.ODTExportError, ex:
- return HttpResponse(content, content_type="application/xhtml")
- response = HttpResponse(
- mimetype='application/vnd.oasis.opendocument.text')
- response['Content-Disposition'] = 'attachment; filename=%s.odt' % \
- filename
- response.write(odtfile)
- return response
- elif doc_type == 'pdf':
- tpl = loader.get_template('sheet_%s_pdf.html' % name)
- content = tpl.render(context_instance)
- result = StringIO.StringIO()
- html = content.encode('utf-8')
- html = html.replace("<table", "<pdf:nextpage/><table repeat='1'")
- pdf = pisa.pisaDocument(StringIO.StringIO(html), result)
- response = HttpResponse(result.getvalue(),
- mimetype='application/pdf')
- response['Content-Disposition'] = 'attachment; filename=%s.pdf' % \
- filename
- if not pdf.err:
- return response
- return HttpResponse(content, content_type="application/xhtml")
- else:
- tpl = loader.get_template('sheet_%s_window.html' % name)
- content = tpl.render(context_instance)
- return HttpResponse(content, content_type="application/xhtml")
- return func
-
-def revert_item(model):
- def func(request, pk, date, **dct):
- try:
- item = model.objects.get(pk=pk)
- date = datetime.datetime.strptime(date, '%Y-%m-%dT%H:%M:%S.%f')
- item.rollback(date)
- except (ObjectDoesNotExist, ValueError, HistoryError):
- return HttpResponse(None, mimetype='text/plain')
- return HttpResponse("True", mimetype='text/plain')
- return func
-
-
-get_file = get_item(models.File, 'get_file', 'file')
-show_file = show_item(models.File, 'file')
-revert_file = revert_item(models.File)
-
-def autocomplete_operation(request, non_closed=True):
- person_types = request.user.ishtaruser.person.person_type
- if (not request.user.has_perm('ishtar_base.view_operation', models.Operation)\
- and not request.user.has_perm('ishtar_base.view_own_operation',
- models.Operation)
- and not person_types.rights.filter(wizard__url_name='operation_search'
- ).count()):
- return HttpResponse(mimetype='text/plain')
- if not request.GET.get('term'):
- return HttpResponse(mimetype='text/plain')
- q = request.GET.get('term')
- query = Q()
- for q in q.split(' '):
- extra = Q(towns__name__icontains=q)
- try:
- value = int(q)
- extra = extra | Q(year=q) | Q(operation_code=q)
- except ValueError:
- pass
- query = query & extra
- if non_closed:
- query = query & Q(end_date__isnull=True)
- limit = 15
- operations = models.Operation.objects.filter(query)[:limit]
- data = json.dumps([{'id':operation.pk, 'value':unicode(operation)}
- for operation in operations])
- return HttpResponse(data, mimetype='text/plain')
-
-def get_available_operation_code(request, year=None):
- if not request.user.has_perm('ishtar_base.view_operation', models.Operation)\
- and not request.user.has_perm('ishtar_base.view_own_operation',
- models.Operation):
- return HttpResponse(mimetype='text/plain')
- data = json.dumps({'id':models.Operation.get_available_operation_code(year)})
- return HttpResponse(data, mimetype='text/plain')
-
-get_operation = get_item(models.Operation, 'get_operation', 'operation',
- bool_fields = ['end_date__isnull'],
- extra_request_keys={'common_name':'common_name__icontains',
- 'end_date':'end_date__isnull',
- 'year_index':('year', 'operation_code')})
-show_operation = show_item(models.Operation, 'operation')
-revert_operation = revert_item(models.Operation)
-
-get_operationsource = get_item(models.OperationSource,
- 'get_operationsource', 'operationsource',
- extra_request_keys={'operation__towns':'operation__towns__pk',
- 'operation__operation_type':'operation__operation_type__pk',
- 'operation__year':'operation__year'})
-
-get_administrativeactfile = get_item(models.AdministrativeAct,
- 'get_administrativeactfile', 'administrativeactfile',
- extra_request_keys={'associated_file__towns':'associated_file__towns__pk',
- 'operation__towns':'operation__towns__pk',
- 'act_type__intented_to':'act_type__intented_to'})
-get_administrativeactop = get_item(models.AdministrativeAct,
- 'get_administrativeactop', 'administrativeactop',
- extra_request_keys={'associated_file__towns':'associated_file__towns__pk',
- 'operation__towns':'operation__towns__pk',
- 'act_type__intented_to':'act_type__intented_to'})
-
-def autocomplete_organization(request, orga_type=None):
- person_types = request.user.ishtaruser.person.person_type
- if (not request.user.has_perm('ishtar_base.view_organization',
- models.Organization) and \
- not request.user.has_perm('ishtar_base.view_own_organization',
- models.Organization)
- and not person_types.rights.filter(wizard__url_name='person_search'
- ).count()):
- return HttpResponse(mimetype='text/plain')
- if not request.GET.get('term'):
- return HttpResponse(mimetype='text/plain')
- q = request.GET.get('term')
- query = Q()
- for q in q.split(' '):
- extra = Q(name__icontains=q)
- query = query & extra
- if orga_type:
- try:
- typs = [int(tp) for tp in orga_type.split('_') if tp]
- typ = models.OrganizationType.objects.filter(pk__in=typs).all()
- query = query & Q(organization_type__in=typ)
- except (ValueError, ObjectDoesNotExist):
- pass
- limit = 15
- organizations = models.Organization.objects.filter(query)[:limit]
- data = json.dumps([{'id':org.pk, 'value':unicode(org)}
- for org in organizations])
- return HttpResponse(data, mimetype='text/plain')
-
-show_contextrecord = show_item(models.ContextRecord, 'contextrecord')
-get_contextrecord = get_item(models.ContextRecord,
- 'get_contextrecord', 'contextrecord',
- extra_request_keys={'parcel__town':'parcel__town__pk',
- 'operation__year':'operation__year__contains',
- 'datings__period':'datings__period__pk'},)
-get_contextrecordsource = get_item(models.ContextRecordSource,
- 'get_contextrecordsource', 'contextrecordsource',
- extra_request_keys={
- 'context_record__parcel__town':'context_record__parcel__town__pk',
- 'context_record__operation__year':'context_record__operation__year',
- 'context_record__datings__period':'context_record__datings__period__pk',
- 'context_record__unit':'context_record__unit__pk',
- })
-get_archaeologicalitem = get_item(models.Item,
- 'get_archaeologicalitem', 'item',
- bool_fields = ['base_items__is_isolated'],
- base_request={'downstream_treatment__isnull':True},
- extra_request_keys={
-'base_items__context_record__parcel__town':
- 'base_items__context_record__parcel__town',
-'base_items__context_record__operation__year':
- 'base_items__context_record__operation__year__contains',
-'base_items__context_record__operation__code_patriarche':
- 'base_items__context_record__operation__code_patriarche',
-'dating__period':'dating__period__pk',
-'base_items__item__description':'base_items__item__description__icontains',
-'base_items__is_isolated':'base_items__is_isolated'})
-get_itemsource = get_item(models.ItemSource,
- 'get_itemsource', 'itemsource',
- extra_request_keys={
-'item__context_record__operation__year':'item__context_record__operation__year',
-'item__dating__period':'item__dating__period__pk',
-'item__description':'item__description__icontains',
- })
-get_container = get_item(models.Container,
- 'get_container', 'container',
- extra_request_keys={
-'location':'location__pk',
-'container_type':'container_type__pk',
-'reference':'reference__icontains',
- })
-
-def autocomplete_warehouse(request):
- if not request.user.has_perm('ishtar_base.view_warehouse', models.Warehouse)\
- and not request.user.has_perm('ishtar_base.view_own_warehouse',
- models.Warehouse) :
- return HttpResponse(mimetype='text/plain')
- if not request.GET.get('term'):
- return HttpResponse(mimetype='text/plain')
- q = request.GET.get('term')
- query = Q()
- for q in q.split(' '):
- extra = Q(name__icontains=q) | \
- Q(warehouse_type__label__icontains=q)
- query = query & extra
- limit = 15
- warehouses = models.Warehouse.objects.filter(query)[:limit]
- data = json.dumps([{'id':warehouse.pk, 'value':unicode(warehouse)}
- for warehouse in warehouses])
- return HttpResponse(data, mimetype='text/plain')
-
-def autocomplete_author(request):
- if not request.user.has_perm('ishtar_base.view_author', models.Author)\
- and not request.user.has_perm('ishtar_base.view_own_author',
- models.Warehouse) :
- return HttpResponse(mimetype='text/plain')
- if not request.GET.get('term'):
- return HttpResponse(mimetype='text/plain')
- q = request.GET.get('term')
- query = Q()
- for q in q.split(' '):
- extra = Q(person__name__icontains=q) | \
- Q(person__surname__icontains=q) | \
- Q(person__email__icontains=q) | \
- Q(author_type__label__icontains=q)
- query = query & extra
- limit = 15
- authors = models.Author.objects.filter(query)[:limit]
- data = json.dumps([{'id':author.pk, 'value':unicode(author)}
- for author in authors])
- return HttpResponse(data, mimetype='text/plain')
-
-def autocomplete_container(request):
- if not request.user.has_perm('ishtar_base.view_warehouse',
- models.Warehouse)\
- and not request.user.has_perm('ishtar_base.view_own_warehouse',
- models.Warehouse):
- return HttpResponse(mimetype='text/plain')
- if not request.GET.get('term'):
- return HttpResponse(mimetype='text/plain')
- q = request.GET.get('term')
- query = Q()
- for q in q.split(' '):
- extra = Q(container_type__label__icontains=q) | \
- Q(container_type__reference__icontains=q) | \
- Q(reference__icontains=q) | \
- Q(location__name=q) | \
- Q(location__town=q)
- query = query & extra
- limit = 15
- containers = models.Container.objects.filter(query)[:limit]
- data = json.dumps([{'id':container.pk, 'value':unicode(container)}
- for container in containers])
- return HttpResponse(data, mimetype='text/plain')
-
-def new_item(model):
- def func(request, parent_name):
- model_name = model._meta.object_name
- if not check_permission(request, 'add_'+model_name.lower()):
- not_permitted_msg = ugettext(u"Operation not permitted.")
- return HttpResponse(not_permitted_msg)
- frm = getattr(ishtar_forms, model_name + 'Form')
- dct = {'title':unicode(_(u'New %s' % model_name.lower()))}
- if request.method == 'POST':
- dct['form'] = frm(request.POST)
- if dct['form'].is_valid():
- new_item = dct['form'].save(request.user)
- dct['new_item_label'] = unicode(new_item)
- dct['new_item_pk'] = new_item.pk
- dct['parent_name'] = parent_name
- dct['parent_pk'] = parent_name
- if dct['parent_pk'] and '_select_' in dct['parent_pk']:
- parents = dct['parent_pk'].split('_')
- dct['parent_pk'] = "_".join([parents[0]] + parents[2:])
- return render_to_response('window.html', dct,
- context_instance=RequestContext(request))
- else:
- dct['form'] = frm()
- return render_to_response('window.html', dct,
- context_instance=RequestContext(request))
- return func
-
-new_warehouse = new_item(models.Warehouse)
-new_person = new_item(models.Person)
-new_organization = new_item(models.Organization)
-new_author = new_item(models.Author)
-new_container = new_item(models.Container)
-
-def action(request, action_slug, obj_id=None, *args, **kwargs):
- """
- Action management
- """
- if not check_permission(request, action_slug, obj_id):
- not_permitted_msg = ugettext(u"Operation not permitted.")
- return HttpResponse(not_permitted_msg)
- request.session['CURRENT_ACTION'] = action_slug
- associated_wizard = action_slug + '_wizard'
- dct = {}
- globals_dct = globals()
- if action_slug in globals_dct:
- return globals_dct[action_slug](request, dct, obj_id, *args, **kwargs)
- elif hasattr(ishtar_forms, action_slug + "_wizard"):
- return getattr(ishtar_forms, action_slug+"_wizard")(request, *args,
- **kwargs)
- return render_to_response('index.html', dct,
- context_instance=RequestContext(request))
-
-def dashboard_main(request, dct, obj_id=None, *args, **kwargs):
- """
- Main dashboard
- """
- dct = {'items':[
- (_(u"Archaeological files"), models.Dashboard(models.File)),
- (_(u"Operations"), models.Dashboard(models.Operation)),
- (_(u"Context records"), models.Dashboard(models.ContextRecord)),
- (_(u"Archaeological items"), models.Dashboard(models.Item)),
- ],
- 'ishtar_users':models.UserDashboard()}
- return render_to_response('dashboard_main.html', dct,
- context_instance=RequestContext(request))
-
-def dashboard_file(request, dct, obj_id=None, *args, **kwargs):
- """
- Main dashboard
- """
- dct = {'dashboard': models.FileDashboard()}
- return render_to_response('dashboard_file.html', dct,
- context_instance=RequestContext(request))
-
-def dashboard_operation(request, dct, obj_id=None, *args, **kwargs):
- """
- Operation dashboard
- """
- dct = {'dashboard': models.OperationDashboard()}
- return render_to_response('dashboard_operation.html', dct,
- context_instance=RequestContext(request))