diff options
Diffstat (limited to 'ishtar_common/views.py')
-rw-r--r-- | ishtar_common/views.py | 496 |
1 files changed, 278 insertions, 218 deletions
diff --git a/ishtar_common/views.py b/ishtar_common/views.py index 0058821b2..fc8151d8d 100644 --- a/ishtar_common/views.py +++ b/ishtar_common/views.py @@ -19,14 +19,14 @@ from tidylib import tidy_document as tidy -import re import csv -import json +import cStringIO as StringIO import datetime +import ho.pisa as pisa +import json import optparse -import cStringIO as StringIO +import re from tempfile import NamedTemporaryFile -import ho.pisa as pisa import unicodedata from extra_views import ModelFormSetView @@ -34,17 +34,17 @@ from extra_views import ModelFormSetView from django.conf import settings from django.contrib.auth import logout from django.contrib.auth.decorators import login_required -from django.core import serializers from django.core.exceptions import ObjectDoesNotExist from django.core.urlresolvers import reverse, NoReverseMatch -from django.db.models import Q, F, ImageField -from django.forms.models import model_to_dict, modelformset_factory -from django.http import HttpResponse, Http404, HttpResponseRedirect +from django.db.models import Q, ImageField +from django.forms.models import modelformset_factory +from django.http import HttpResponse, Http404, HttpResponseRedirect, \ + HttpResponseBadRequest from django.shortcuts import render_to_response, redirect from django.template import RequestContext, loader from django.utils.decorators import method_decorator from django.utils.translation import ugettext, ugettext_lazy as _ -from django.views.generic import ListView, UpdateView, CreateView +from django.views.generic import ListView, UpdateView from django.views.generic.edit import CreateView, DeleteView from xhtml2odt import xhtml2odt @@ -56,11 +56,14 @@ from archaeological_operations.forms import DashboardForm as DashboardFormOpe from ishtar_common.forms import FinalForm, FinalDeleteForm from ishtar_common import forms_common as forms from ishtar_common import wizards +from ishtar_common.models import HistoryError + import models -CSV_OPTIONS = {'delimiter':';', 'quotechar':'"', 'quoting':csv.QUOTE_ALL} +CSV_OPTIONS = {'delimiter': ';', 'quotechar': '"', 'quoting': csv.QUOTE_ALL} ENCODING = settings.ENCODING or 'utf-8' + def index(request): """ Main page @@ -68,69 +71,70 @@ def index(request): dct = {} try: return render_to_response('index.html', dct, - context_instance=RequestContext(request)) + context_instance=RequestContext(request)) except NoReverseMatch: # probably rights exception (rights revoked) logout(request) return render_to_response('index.html', dct, - context_instance=RequestContext(request)) + context_instance=RequestContext(request)) + +person_search_wizard = wizards.SearchWizard.as_view( + [('general-person_search', forms.PersonFormSelection)], + label=_(u"Person search"), + url_name='person_search',) + +person_creation_wizard = wizards.PersonWizard.as_view( + [('identity-person_creation', forms.SimplePersonForm), + ('person_type-person_creation', forms.PersonTypeForm), + ('final-person_creation', FinalForm)], + label=_(u"New person"), + url_name='person_creation') + +person_modification_wizard = wizards.PersonModifWizard.as_view( + [('selec-person_modification', forms.PersonFormSelection), + ('identity-person_modification', forms.SimplePersonForm), + ('person_type-person_creation', forms.PersonTypeForm), + ('final-person_modification', FinalForm)], + label=_(u"Person modification"), + url_name='person_modification') + +person_deletion_wizard = wizards.PersonDeletionWizard.as_view( + [('selec-person_deletion', forms.PersonFormSelection), + ('final-person_deletion', FinalDeleteForm)], + label=_(u"Person deletion"), + url_name='person_deletion',) + +organization_search_wizard = wizards.SearchWizard.as_view( + [('general-organization_search', forms.OrganizationFormSelection)], + label=_(u"Organization search"), + url_name='organization_search',) + +organization_creation_wizard = wizards.OrganizationWizard.as_view( + [('identity-organization_creation', forms.OrganizationForm), + ('final-organization_creation', FinalForm)], + label=_(u"New organization"), + url_name='organization_creation') + +organization_modification_wizard = wizards.OrganizationModifWizard.as_view( + [('selec-organization_modification', forms.OrganizationFormSelection), + ('identity-organization_modification', forms.OrganizationForm), + ('final-organization_modification', FinalForm)], + label=_(u"Organization modification"), + url_name='organization_modification') + +organization_deletion_wizard = wizards.OrganizationDeletionWizard.as_view( + [('selec-organization_deletion', forms.OrganizationFormSelection), + ('final-organization_deletion', FinalDeleteForm)], + label=_(u"Organization deletion"), + url_name='organization_deletion',) + +account_management_wizard = wizards.AccountWizard.as_view( + [('selec-account_management', forms.PersonFormSelection), + ('account-account_management', forms.AccountForm), + ('final-account_management', forms.FinalAccountForm)], + label=_(u"Account management"), + url_name='account_management',) -person_search_wizard = wizards.SearchWizard.as_view([ - ('general-person_search', forms.PersonFormSelection)], - label=_(u"Person search"), - url_name='person_search',) - -person_creation_wizard = wizards.PersonWizard.as_view([ - ('identity-person_creation', forms.SimplePersonForm), - ('person_type-person_creation', forms.PersonTypeForm), - ('final-person_creation', FinalForm)], - label=_(u"New person"), - url_name='person_creation') - -person_modification_wizard = wizards.PersonModifWizard.as_view([ - ('selec-person_modification', forms.PersonFormSelection), - ('identity-person_modification', forms.SimplePersonForm), - ('person_type-person_creation', forms.PersonTypeForm), - ('final-person_modification', FinalForm)], - label=_(u"Person modification"), - url_name='person_modification') - -person_deletion_wizard = wizards.PersonDeletionWizard.as_view([ - ('selec-person_deletion', forms.PersonFormSelection), - ('final-person_deletion', FinalDeleteForm)], - label=_(u"Person deletion"), - url_name='person_deletion',) - -organization_search_wizard = wizards.SearchWizard.as_view([ - ('general-organization_search', forms.OrganizationFormSelection)], - label=_(u"Organization search"), - url_name='organization_search',) - -organization_creation_wizard = wizards.OrganizationWizard.as_view([ - ('identity-organization_creation', forms.OrganizationForm), - ('final-organization_creation', FinalForm)], - label=_(u"New organization"), - url_name='organization_creation') - -organization_modification_wizard = wizards.OrganizationModifWizard.as_view([ - ('selec-organization_modification', forms.OrganizationFormSelection), - ('identity-organization_modification', forms.OrganizationForm), - ('final-organization_modification', FinalForm)], - label=_(u"Organization modification"), - url_name='organization_modification') - -organization_deletion_wizard = wizards.OrganizationDeletionWizard.as_view([ - ('selec-organization_deletion', forms.OrganizationFormSelection), - ('final-organization_deletion', FinalDeleteForm)], - label=_(u"Organization deletion"), - url_name='organization_deletion',) - -account_management_wizard = wizards.AccountWizard.as_view([ - ('selec-account_management', forms.PersonFormSelection), - ('account-account_management', forms.AccountForm), - ('final-account_management', forms.FinalAccountForm)], - label=_(u"Account management"), - url_name='account_management',) def update_current_item(request): if not request.is_ajax() and not request.method == 'POST': @@ -139,15 +143,18 @@ def update_current_item(request): 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 + # 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_types=None, is_ishtar_user=None): + +def autocomplete_person(request, person_types=None, attached_to=None, + is_ishtar_user=None): if not request.user.has_perm('ishtar_common.view_person', models.Person) and \ not request.user.has_perm('ishtar_common.view_own_person', models.Person) \ and not request.user.ishtaruser.has_right('person_search'): @@ -162,9 +169,13 @@ def autocomplete_person(request, person_types=None, is_ishtar_user=None): return HttpResponseBadRequest() query = Q() for q in q.split(' '): - query = query & (Q(name__icontains=q) | Q(surname__icontains=q) | \ - Q(email__icontains=q) | Q(attached_to__name__icontains=q)) - if person_types and unicode(person_types) != '0': + query = query & (Q(name__icontains=q) | Q(surname__icontains=q) | + Q(email__icontains=q) | + Q(attached_to__name__icontains=q)) + if attached_to: + query = query & Q(attached_to__pk__in=attached_to.split('_')) + + if person_types and unicode(person_types) != '0': try: typs = [int(tp) for tp in person_types.split('_') if tp] typ = models.PersonType.objects.filter(pk__in=typs).all() @@ -175,48 +186,51 @@ def autocomplete_person(request, person_types=None, is_ishtar_user=None): query = query & Q(ishtaruser__isnull=False) limit = 20 persons = models.Person.objects.filter(query)[:limit] - data = json.dumps([{'id':person.pk, 'value':unicode(person)} - for person in persons if person]) + data = json.dumps([{'id': person.pk, 'value': unicode(person)} + for person in persons if person]) return HttpResponse(data, mimetype='text/plain') + def autocomplete_department(request): if not request.GET.get('term'): return HttpResponse(mimetype='text/plain') q = request.GET.get('term') - q = unicodedata.normalize("NFKD", q).encode('ascii','ignore') + q = unicodedata.normalize("NFKD", q).encode('ascii', 'ignore') query = Q() for q in q.split(' '): extra = (Q(label__icontains=q) | Q(number__istartswith=q)) query = query & extra limit = 20 departments = models.Department.objects.filter(query)[:limit] - data = json.dumps([{'id':department.pk, 'value':unicode(department)} - for department in departments]) + data = json.dumps([{'id': department.pk, 'value': unicode(department)} + for department in departments]) 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') - q = unicodedata.normalize("NFKD", q).encode('ascii','ignore') + q = unicodedata.normalize("NFKD", q).encode('ascii', 'ignore') 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)) + 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]) + data = json.dumps([{'id': town.pk, 'value': unicode(town)} + for town in towns]) return HttpResponse(data, mimetype='text/plain') + def autocomplete_advanced_town(request, department_id=None, state_id=None): if not request.GET.get('term'): return HttpResponse(mimetype='text/plain') q = request.GET.get('term') - q = unicodedata.normalize("NFKD", q).encode('ascii','ignore') + q = unicodedata.normalize("NFKD", q).encode('ascii', 'ignore') query = Q() for q in q.split(' '): extra = Q(name__icontains=q) @@ -236,25 +250,24 @@ def autocomplete_advanced_town(request, department_id=None, state_id=None): val = town.name if hasattr(town, 'numero_insee'): val += " (%s)" % town.numero_insee - result.append({'id':town.pk, 'value':val}) + result.append({'id': town.pk, 'value': val}) data = json.dumps(result) return HttpResponse(data, mimetype='text/plain') + def department_by_state(request, state_id=''): if not state_id: data = [] else: departments = models.Department.objects.filter(state__number=state_id) - data = json.dumps([{'id':department.pk, 'number':department.number, - 'value':unicode(department)} - for department in departments]) + data = json.dumps([{'id': department.pk, 'number': department.number, + 'value': unicode(department)} + for department in departments]) return HttpResponse(data, mimetype='text/plain') -from types import NoneType - def format_val(val): - if type(val) == NoneType: + if val is None: return u"" if type(val) == bool: if val: @@ -267,33 +280,33 @@ HIERARCHIC_LEVELS = 5 HIERARCHIC_FIELDS = ['periods', 'period', 'unit', 'material_type', 'conservatory_state'] PRIVATE_FIELDS = ('id', 'history_modifier', 'order') + + def get_item(model, func_name, default_name, extra_request_keys=[], - base_request={}, bool_fields=[], reversed_bool_fields=[], - dated_fields=[], associated_models=[], relative_session_names={}, - specific_perms=[]): + base_request={}, bool_fields=[], reversed_bool_fields=[], + dated_fields=[], associated_models=[], relative_session_names={}, + specific_perms=[]): """ Generic treatment of tables """ def func(request, data_type='json', full=False, **dct): # check rights - own = True # more restrictive by default + own = True # more restrictive by default allowed = False for perm, lbl in model._meta.permissions: # if not specific any perm is relevant (read right) if specific_perms and perm not in specific_perms: continue if request.user.has_perm(model._meta.app_label + '.' + perm) \ - or (request.user.is_authenticated() - and request.user.ishtaruser.has_right(perm)): + or (request.user.is_authenticated() + and request.user.ishtaruser.has_right(perm)): allowed = True if "_own_" not in perm: own = False - break # max right reach - EMPTY, mimetype = '', 'text/plain' + break # max right reach + EMPTY = '' if 'type' in dct: data_type = dct.pop('type') - if data_type == 'csv': - mimetype = 'text/csv' if not data_type: EMPTY = '[]' data_type = 'json' @@ -301,18 +314,23 @@ def get_item(model, func_name, default_name, extra_request_keys=[], return HttpResponse(EMPTY, mimetype='text/plain') 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 = dict([ + (field.name, + field.name + (hasattr(field, 'rel') and field.rel and '__pk' + or '')) + for field in fields]) for associated_model, key in associated_models: - associated_fields = [associated_model._meta.get_field_by_name(k)[0] - for k in associated_model._meta.get_all_field_names()] - request_keys.update(dict([(key + "__" + field.name, - key + "__" + field.name + (hasattr(field, 'rel') and - field.rel and '__pk' or '')) - for field in associated_fields])) + associated_fields = [ + associated_model._meta.get_field_by_name(k)[0] + for k in associated_model._meta.get_all_field_names()] + request_keys.update( + dict([(key + "__" + field.name, + key + "__" + field.name + + (hasattr(field, 'rel') and field.rel and '__pk' or '')) + for field in associated_fields])) request_keys.update(extra_request_keys) - request_items = request.method == 'POST' and request.POST or request.GET + request_items = request.method == 'POST' and request.POST \ + or request.GET dct = base_request.copy() and_reqs, or_reqs = [], [] try: @@ -327,14 +345,15 @@ def get_item(model, func_name, default_name, extra_request_keys=[], 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]} + dct = {"pk": request.session[default_name]} else: for name in relative_session_names.keys(): if name in request.session and request.session[name]: k = relative_session_names[name] - dct = {k:request.session[name]} + dct = {k: request.session[name]} break - if (not dct or data_type == 'csv') and func_name in request.session: + if (not dct or data_type == 'csv') \ + and func_name in request.session: dct = request.session[func_name] else: request.session[func_name] = dct @@ -351,7 +370,8 @@ def get_item(model, func_name, default_name, extra_request_keys=[], if k.endswith('__isnull') and \ isinstance(c_field, ImageField): if dct[k]: - or_reqs.append((k, {k.split('__')[0]+'__exact':''})) + or_reqs.append( + (k, {k.split('__')[0]+'__exact': ''})) else: dct[k.split('__')[0]+'__regex'] = '.{1}.*' for k in dated_fields: @@ -362,8 +382,8 @@ def get_item(model, func_name, default_name, extra_request_keys=[], items = dct[k].split('/') assert len(items) == 3 dct[k] = datetime.date(*map(lambda x: int(x), - reversed(items)) - ).strftime('%Y-%m-%d') + reversed(items)))\ + .strftime('%Y-%m-%d') except AssertionError: dct.pop(k) # manage hierarchic conditions @@ -374,18 +394,18 @@ def get_item(model, func_name, default_name, extra_request_keys=[], q = None for idx, r in enumerate(req): if not idx: - q = Q(**{r:val}) + q = Q(**{r: val}) else: - q = q | Q(**{r:val}) + q = q | Q(**{r: val}) and_reqs.append(q) break elif req.endswith(k_hr + '__pk'): val = dct.pop(req) - reqs = Q(**{req:val}) + reqs = Q(**{req: val}) req = req[:-2] + '__' for idx in xrange(HIERARCHIC_LEVELS): req = req[:-2] + 'parent__pk' - q = Q(**{req:val}) + q = Q(**{req: val}) reqs = reqs | q and_reqs.append(reqs) break @@ -405,7 +425,7 @@ def get_item(model, func_name, default_name, extra_request_keys=[], # table cols table_cols = full and [field.name for field in model._meta.fields if field.name not in PRIVATE_FIELDS] \ - or model.TABLE_COLS + or model.TABLE_COLS # manage sort tables manual_sort_key = None order = request_items.get('sord') @@ -461,14 +481,15 @@ def get_item(model, func_name, default_name, extra_request_keys=[], for ky in k.split('.'): new_vals = [] for val in vals: - if hasattr(val, 'all'): # manage related objects + 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 + # manage last related objects + if vals and hasattr(vals[0], 'all'): new_vals = [] for val in vals: new_vals += list(val.all()) @@ -478,32 +499,33 @@ def get_item(model, func_name, default_name, extra_request_keys=[], if manual_sort_key: # +1 because the id is added as a first col idx_col = table_cols.index(manual_sort_key) + 1 - datas = sorted(datas, key=lambda x:x[idx_col]) + datas = sorted(datas, key=lambda x: x[idx_col]) if sign == '-': datas = reversed(datas) datas = list(datas)[start:end] - link_template = "<a class='display_details' href='#' onclick='load_window(\"%%s\")'>%s</a>" % \ + link_template = "<a class='display_details' 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], '']) + args=[data[0], '']) except NoReverseMatch: print '"show-' + default_name + "\" args (" + \ unicode(data[0]) + ") url not available" lnk = '' - res = {'id':data[0], 'link':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) if row_nb else items_nb, + "records": items_nb, + "rows": rows, + "page": page_nb, + "total": (items_nb/row_nb + 1) if row_nb else items_nb, }) return HttpResponse(data, mimetype='text/plain') elif data_type == "csv": @@ -511,7 +533,8 @@ def get_item(model, func_name, default_name, extra_request_keys=[], 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 + response['Content-Disposition'] = 'attachment; filename=%s'\ + % filename writer = csv.writer(response, **CSV_OPTIONS) col_names = [] for field_name in table_cols: @@ -529,6 +552,7 @@ def get_item(model, func_name, default_name, extra_request_keys=[], return func + def show_item(model, name, extra_dct=None): def func(request, pk, **dct): try: @@ -540,15 +564,15 @@ def show_item(model, name, extra_dct=None): ).split('/')[:-2]) + u"/" dct['current_window_url'] = url_name date = 'date' in dct and dct.pop('date') - dct['window_id'] = "%s-%d-%s" % (name, item.pk, - datetime.datetime.now().strftime('%M%s')) + dct['window_id'] = "%s-%d-%s" % ( + name, item.pk, datetime.datetime.now().strftime('%M%s')) if hasattr(item, 'history'): if date: try: date = datetime.datetime.strptime(date, '%Y-%m-%dT%H:%M:%S.%f') item = item.get_previous(date=date) - assert item != None + assert item is not None except (ValueError, AssertionError): return HttpResponse(None, mimetype='text/plain') dct['previous'] = item._previous @@ -565,7 +589,6 @@ def show_item(model, name, extra_dct=None): dct.update(extra_dct(request, item)) context_instance = RequestContext(request) context_instance.update(dct) - n = datetime.datetime.now() filename = "" if hasattr(item, 'history_object'): filename = item.history_object.associated_filename @@ -575,9 +598,9 @@ def show_item(model, name, extra_dct=None): tpl = loader.get_template('ishtar/sheet_%s.html' % name) content = tpl.render(context_instance) try: - tidy_options = {'output-xhtml':1, 'indent':1, - 'tidy-mark':0, 'doctype':'auto', - 'add-xml-decl':1, 'wrap':1} + tidy_options = {'output-xhtml': 1, 'indent': 1, + 'tidy-mark': 0, 'doctype': 'auto', + 'add-xml-decl': 1, 'wrap': 1} html, errors = tidy(content, options=tidy_options) html = html.encode('utf-8').replace(" ", " ") html = re.sub('<pre([^>]*)>\n', '<pre\\1>', html) @@ -602,12 +625,12 @@ def show_item(model, name, extra_dct=None): odtfile.open() odtfile.import_xhtml(html) odtfile = odtfile.save() - except xhtml2odt.ODTExportError, ex: + except xhtml2odt.ODTExportError: return HttpResponse(content, content_type="application/xhtml") response = HttpResponse( - mimetype='application/vnd.oasis.opendocument.text') + mimetype='application/vnd.oasis.opendocument.text') response['Content-Disposition'] = 'attachment; filename=%s.odt' % \ - filename + filename response.write(odtfile) return response elif doc_type == 'pdf': @@ -621,7 +644,7 @@ def show_item(model, name, extra_dct=None): response = HttpResponse(result.getvalue(), mimetype='application/pdf') response['Content-Disposition'] = 'attachment; filename=%s.pdf' % \ - filename + filename if not pdf.err: return response return HttpResponse(content, content_type="application/xhtml") @@ -631,6 +654,7 @@ def show_item(model, name, extra_dct=None): return HttpResponse(content, content_type="application/xhtml") return func + def revert_item(model): def func(request, pk, date, **dct): try: @@ -642,11 +666,12 @@ def revert_item(model): return HttpResponse("True", mimetype='text/plain') return func + def autocomplete_organization(request, orga_type=None): if (not request.user.has_perm('ishtar_common.view_organization', - models.Organization) and \ - not request.user.has_perm('ishtar_common.view_own_organization', - models.Organization) + models.Organization) and + not request.user.has_perm('ishtar_common.view_own_organization', + models.Organization) and not request.user.ishtaruser.has_right('person_search')): return HttpResponse(mimetype='text/plain') if not request.GET.get('term'): @@ -665,14 +690,15 @@ def autocomplete_organization(request, orga_type=None): pass limit = 15 organizations = models.Organization.objects.filter(query)[:limit] - data = json.dumps([{'id':org.pk, 'value':unicode(org)} - for org in organizations]) + data = json.dumps([{'id': org.pk, 'value': unicode(org)} + for org in organizations]) return HttpResponse(data, mimetype='text/plain') + def autocomplete_author(request): if not request.user.has_perm('ishtar_common.view_author', models.Author)\ and not request.user.has_perm('ishtar_common.view_own_author', - models.Author) : + models.Author): return HttpResponse(mimetype='text/plain') if not request.GET.get('term'): return HttpResponse(mimetype='text/plain') @@ -680,23 +706,24 @@ def autocomplete_author(request): 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) + 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]) + data = json.dumps([{'id': author.pk, 'value': unicode(author)} + for author in authors]) return HttpResponse(data, mimetype='text/plain') + def new_item(model, frm): def func(request, parent_name, limits=''): 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) - dct = {'title':unicode(_(u'New %s' % model_name.lower()))} + dct = {'title': unicode(_(u'New %s' % model_name.lower()))} if request.method == 'POST': dct['form'] = frm(request.POST, limits=limits) if dct['form'].is_valid(): @@ -708,8 +735,9 @@ def new_item(model, frm): 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)) + return render_to_response( + 'window.html', dct, + context_instance=RequestContext(request)) else: dct['form'] = frm(limits=limits) return render_to_response('window.html', dct, @@ -717,24 +745,28 @@ def new_item(model, frm): return func new_person = new_item(models.Person, forms.PersonForm) +new_person_noorga = new_item(models.Person, forms.NoOrgaPersonForm) new_organization = new_item(models.Organization, forms.OrganizationForm) show_organization = show_item(models.Organization, 'organization') -get_organization = get_item(models.Organization, - 'get_organization', 'organization', - extra_request_keys={ - 'name':'name__icontains', - 'organization_type':'organization_type__pk__in', - },) +get_organization = get_item( + models.Organization, + 'get_organization', 'organization', + extra_request_keys={ + 'name': 'name__icontains', + 'organization_type': 'organization_type__pk__in', + }) new_author = new_item(models.Author, forms.AuthorForm) show_person = show_item(models.Person, 'person') -get_person = get_item(models.Person, - 'get_person', 'person', - extra_request_keys={ - 'name':'name__icontains', - 'surname':'surname__icontains', - 'attached_to':'attached_to__pk', - 'person_types':'person_types__pk__in', - },) +get_person = get_item( + models.Person, + 'get_person', 'person', + extra_request_keys={ + 'name': 'name__icontains', + 'surname': 'surname__icontains', + 'attached_to': 'attached_to__pk', + 'person_types': 'person_types__pk__in', + }) + def action(request, action_slug, obj_id=None, *args, **kwargs): """ @@ -744,7 +776,6 @@ def action(request, action_slug, obj_id=None, *args, **kwargs): 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: @@ -752,6 +783,7 @@ def action(request, action_slug, obj_id=None, *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 @@ -764,9 +796,9 @@ def dashboard_main(request, dct, obj_id=None, *args, **kwargs): app_list.append((_(u"Context records"), 'contextrecords')) if 'archaeological_finds' in settings.INSTALLED_APPS: app_list.append((_(u"Finds"), 'finds')) - dct = {'app_list':app_list} + dct = {'app_list': app_list} return render_to_response('ishtar/dashboards/dashboard_main.html', dct, - context_instance=RequestContext(request)) + context_instance=RequestContext(request)) DASHBOARD_FORMS = {} if 'archaeological_files' in settings.INSTALLED_APPS: @@ -775,20 +807,21 @@ if 'archaeological_files' in settings.INSTALLED_APPS: DASHBOARD_FORMS['operations'] = DashboardFormOpe + def dashboard_main_detail(request, item_name): """ Specific tab of the main dashboard """ if item_name == 'users': - dct = {'ishtar_users':models.UserDashboard()} + dct = {'ishtar_users': models.UserDashboard()} return render_to_response( - 'ishtar/dashboards/dashboard_main_detail_users.html', - dct, context_instance=RequestContext(request)) + 'ishtar/dashboards/dashboard_main_detail_users.html', + dct, context_instance=RequestContext(request)) form = None - slicing, date_source, fltr, show_detail = 'year', None, {}, False - if (item_name == 'files' and \ - 'archaeological_files' in settings.INSTALLED_APPS) \ - or item_name == 'operations': + slicing, date_source, fltr, show_detail = 'year', None, {}, False + if (item_name == 'files' and + 'archaeological_files' in settings.INSTALLED_APPS) \ + or item_name == 'operations': slicing = 'month' if item_name in DASHBOARD_FORMS: if request.method == 'POST': @@ -803,16 +836,16 @@ def dashboard_main_detail(request, item_name): else: form = DASHBOARD_FORMS[item_name]() lbl, dashboard = None, None - if (item_name == 'files' and \ - 'archaeological_files' in settings.INSTALLED_APPS) \ - or item_name == 'operations': - dashboard_kwargs = {'slice':slicing, 'fltr':fltr, - 'show_detail':show_detail} + if (item_name == 'files' and + 'archaeological_files' in settings.INSTALLED_APPS) \ + or item_name == 'operations': + dashboard_kwargs = {'slice': slicing, 'fltr': fltr, + 'show_detail': show_detail} # date_source is only relevant when the form has set one if date_source: dashboard_kwargs['date_source'] = date_source if item_name == 'files' and \ - 'archaeological_files' in settings.INSTALLED_APPS: + 'archaeological_files' in settings.INSTALLED_APPS: from archaeological_files.models import File lbl, dashboard = (_(u"Archaeological files"), models.Dashboard(File, **dashboard_kwargs)) @@ -821,26 +854,29 @@ def dashboard_main_detail(request, item_name): lbl, dashboard = (_(u"Operations"), models.Dashboard(Operation, **dashboard_kwargs)) if item_name == 'contextrecords' and \ - 'archaeological_context_records' in settings.INSTALLED_APPS: + 'archaeological_context_records' in settings.INSTALLED_APPS: from archaeological_context_records.models import ContextRecord - lbl, dashboard = (_(u"Context records"), models.Dashboard(ContextRecord, - slice=slicing, fltr=fltr)) + lbl, dashboard = ( + _(u"Context records"), + models.Dashboard(ContextRecord, slice=slicing, fltr=fltr)) if item_name == 'finds' and \ - 'archaeological_finds' in settings.INSTALLED_APPS: + 'archaeological_finds' in settings.INSTALLED_APPS: from archaeological_finds.models import Find lbl, dashboard = (_(u"Finds"), models.Dashboard(Find, - slice=slicing, fltr=fltr)) + slice=slicing, + fltr=fltr)) if not lbl: raise Http404 - dct = {'lbl':lbl, 'dashboard':dashboard, - 'item_name':item_name.replace('-', '_'), + dct = {'lbl': lbl, 'dashboard': dashboard, + 'item_name': item_name.replace('-', '_'), 'VALUE_QUOTE': '' if slicing == "year" else "'", - 'form':form, 'slicing':slicing} + 'form': form, 'slicing': slicing} n = datetime.datetime.now() dct['unique_id'] = dct['item_name'] + "_" + \ - '%d_%d_%d' % (n.minute, n.second, n.microsecond) + '%d_%d_%d' % (n.minute, n.second, n.microsecond) return render_to_response('ishtar/dashboards/dashboard_main_detail.html', - dct, context_instance=RequestContext(request)) + dct, context_instance=RequestContext(request)) + def reset_wizards(request): # dynamicaly execute each reset_wizards of each ishtar app @@ -857,18 +893,21 @@ def reset_wizards(request): return redirect(reverse('start')) ITEM_PER_PAGE = 20 + + def merge_action(model, form, key): def merge(request, page=1): current_url = key + '_merge' if not page: page = 1 page = int(page) - FormSet = modelformset_factory(model.merge_candidate.through, - form=form, formset=forms.MergeFormSet ,extra=0) + FormSet = modelformset_factory( + model.merge_candidate.through, form=form, + formset=forms.MergeFormSet, extra=0) q = model.merge_candidate.through.objects - context = {'current_url':current_url, - 'current_page':page, - 'max_page':q.count()/ITEM_PER_PAGE} + context = {'current_url': current_url, + 'current_page': page, + 'max_page': q.count()/ITEM_PER_PAGE} if page < context["max_page"]: context['next_page'] = page + 1 if page > 1: @@ -885,25 +924,32 @@ def merge_action(model, form, key): context['formset'] = FormSet(request.POST, queryset=queryset) if context['formset'].is_valid(): context['formset'].merge() - return redirect(reverse(current_url, kwargs={'page':page})) + return redirect(reverse(current_url, kwargs={'page': page})) else: context['formset'] = FormSet(queryset=queryset) - return render_to_response('ishtar/merge_'+key+'.html', context, - context_instance=RequestContext(request)) + return render_to_response( + 'ishtar/merge_'+key+'.html', context, + context_instance=RequestContext(request)) return merge person_merge = merge_action(models.Person, forms.MergePersonForm, 'person') -organization_merge = merge_action(models.Organization, forms.MergeOrganizationForm, - 'organization') +organization_merge = merge_action( + models.Organization, + forms.MergeOrganizationForm, + 'organization' +) + class IshtarMixin(object): page_name = u"" + def get_context_data(self, **kwargs): context = super(IshtarMixin, self).get_context_data(**kwargs) context['page_name'] = self.page_name return context + class LoginRequiredMixin(object): @method_decorator(login_required) def dispatch(self, request, *args, **kwargs): @@ -915,12 +961,14 @@ class LoginRequiredMixin(object): return super(LoginRequiredMixin, self).dispatch(request, *args, **kwargs) + class AdminLoginRequiredMixin(LoginRequiredMixin): def dispatch(self, request, *args, **kwargs): if not request.user.is_staff: return redirect(reverse('start')) - return super(AdminLoginRequiredMixin, self).dispatch(request, *args, - **kwargs) + return super(AdminLoginRequiredMixin, self).dispatch( + request, *args, **kwargs) + class GlobalVarEdit(IshtarMixin, AdminLoginRequiredMixin, ModelFormSetView): template_name = 'ishtar/formset.html' @@ -930,6 +978,7 @@ class GlobalVarEdit(IshtarMixin, AdminLoginRequiredMixin, ModelFormSetView): page_name = _(u"Global variables") fields = ['slug', 'value', 'description'] + class NewImportView(IshtarMixin, LoginRequiredMixin, CreateView): template_name = 'ishtar/form.html' model = models.Import @@ -944,6 +993,7 @@ class NewImportView(IshtarMixin, LoginRequiredMixin, CreateView): self.object = form.save(user=user) return HttpResponseRedirect(self.get_success_url()) + class ImportListView(IshtarMixin, LoginRequiredMixin, ListView): template_name = 'ishtar/import_list.html' model = models.Import @@ -952,8 +1002,8 @@ class ImportListView(IshtarMixin, LoginRequiredMixin, ListView): def get_queryset(self): user = models.IshtarUser.objects.get(pk=self.request.user.pk) - return self.model.objects.filter(user=user).exclude(state='AC' - ).order_by('-creation_date') + return self.model.objects.filter(user=user).exclude( + state='AC').order_by('-creation_date') def post(self, request, *args, **kwargs): for field in request.POST: @@ -972,7 +1022,7 @@ class ImportListView(IshtarMixin, LoginRequiredMixin, ListView): action = request.POST[field] if action == 'D': return HttpResponseRedirect(reverse('import_delete', - kwargs={'pk':imprt.pk})) + kwargs={'pk': imprt.pk})) elif action == 'A': imprt.initialize() elif action == 'I': @@ -981,12 +1031,15 @@ class ImportListView(IshtarMixin, LoginRequiredMixin, ListView): imprt.archive() return HttpResponseRedirect(reverse(self.current_url)) + class ImportOldListView(ImportListView): current_url = 'old_imports' + def get_queryset(self): user = models.IshtarUser.objects.get(pk=self.request.user.pk) - return self.model.objects.filter(user=user, state='AC' - ).order_by('-creation_date') + return self.model.objects.filter( + user=user, state='AC').order_by('-creation_date') + class ImportLinkView(IshtarMixin, LoginRequiredMixin, ModelFormSetView): template_name = 'ishtar/formset.html' @@ -996,12 +1049,13 @@ class ImportLinkView(IshtarMixin, LoginRequiredMixin, ModelFormSetView): form_class = forms.TargetKeyForm def get_queryset(self): - return self.model.objects.filter(is_set=False, - associated_import=self.kwargs['pk']) + return self.model.objects.filter( + is_set=False, associated_import=self.kwargs['pk']) def get_success_url(self): return reverse('current_imports') + class ImportDeleteView(IshtarMixin, LoginRequiredMixin, DeleteView): template_name = 'ishtar/import_delete.html' model = models.Import @@ -1010,6 +1064,7 @@ class ImportDeleteView(IshtarMixin, LoginRequiredMixin, DeleteView): def get_success_url(self): return reverse('current_imports') + class PersonCreate(LoginRequiredMixin, CreateView): model = models.Person form_class = forms.BasePersonForm @@ -1018,6 +1073,7 @@ class PersonCreate(LoginRequiredMixin, CreateView): def get_success_url(self): return reverse('person_edit', args=[self.object.pk]) + class PersonEdit(LoginRequiredMixin, UpdateView): model = models.Person form_class = forms.BasePersonForm @@ -1026,6 +1082,7 @@ class PersonEdit(LoginRequiredMixin, UpdateView): def get_success_url(self): return reverse('person_edit', args=[self.object.pk]) + class OrganizationCreate(LoginRequiredMixin, CreateView): model = models.Organization form_class = forms.BaseOrganizationForm @@ -1038,6 +1095,7 @@ class OrganizationCreate(LoginRequiredMixin, CreateView): kwargs.update({'prefix': self.form_class.form_prefix}) return kwargs + class OrganizationEdit(LoginRequiredMixin, UpdateView): model = models.Organization form_class = forms.BaseOrganizationForm @@ -1049,6 +1107,7 @@ class OrganizationEdit(LoginRequiredMixin, UpdateView): kwargs.update({'prefix': self.form_class.form_prefix}) return kwargs + class OrganizationPersonCreate(LoginRequiredMixin, CreateView): model = models.Person form_class = forms.BaseOrganizationPersonForm @@ -1064,6 +1123,7 @@ class OrganizationPersonCreate(LoginRequiredMixin, CreateView): def get_success_url(self): return reverse('organization_person_edit', args=[self.object.pk]) + class OrganizationPersonEdit(LoginRequiredMixin, UpdateView): model = models.Person form_class = forms.BaseOrganizationPersonForm @@ -1072,7 +1132,7 @@ class OrganizationPersonEdit(LoginRequiredMixin, UpdateView): def get_context_data(self, *args, **kwargs): data = super(OrganizationPersonEdit, self).get_context_data(*args, - **kwargs) + **kwargs) data['relative_label'] = self.relative_label return data |