summaryrefslogtreecommitdiff
path: root/ishtar_common
diff options
context:
space:
mode:
Diffstat (limited to 'ishtar_common')
-rw-r--r--ishtar_common/forms.py63
-rw-r--r--ishtar_common/forms_common.py268
-rw-r--r--ishtar_common/templates/blocks/JQueryAutocomplete.js21
-rw-r--r--ishtar_common/templatetags/replace_underscore.py1
-rw-r--r--ishtar_common/urls.py188
-rw-r--r--ishtar_common/views.py496
-rw-r--r--ishtar_common/widgets.py178
-rw-r--r--ishtar_common/wizards.py168
8 files changed, 779 insertions, 604 deletions
diff --git a/ishtar_common/forms.py b/ishtar_common/forms.py
index e6f21ae5b..a5abdddcd 100644
--- a/ishtar_common/forms.py
+++ b/ishtar_common/forms.py
@@ -22,27 +22,18 @@ Forms definition
"""
import datetime
import re
-from itertools import groupby
from django import forms
-from django.conf import settings
-from django.contrib.auth.models import User
-from django.contrib.sites.models import Site
from django.core.urlresolvers import reverse
from django.core import validators
-from django.core.exceptions import ObjectDoesNotExist
-from django.core.mail import send_mail
-from django.db.models import Max
-from django.forms.formsets import formset_factory, BaseFormSet, \
- DELETION_FIELD_NAME
-from django.shortcuts import render_to_response
-from django.template import Context, RequestContext, loader
+from django.forms.formsets import BaseFormSet, DELETION_FIELD_NAME
from django.utils import formats
from django.utils.functional import lazy
from django.utils.translation import ugettext_lazy as _
# from formwizard.forms import NamedUrlSessionFormWizard
+
class NamedUrlSessionFormWizard(forms.Form):
def __init__(self, form_list, condition_list={}, url_name=''):
self.form_list = dict(form_list)
@@ -59,8 +50,11 @@ import widgets
reverse_lazy = lazy(reverse, unicode)
regexp_name = re.compile(r"^[,:/\w\-'\"() \&\[\]@]+$", re.UNICODE)
-name_validator = validators.RegexValidator(regexp_name,
-_(u"Enter a valid name consisting of letters, spaces and hyphens."), 'invalid')
+name_validator = validators.RegexValidator(
+ regexp_name,
+ _(u"Enter a valid name consisting of letters, spaces and hyphens."),
+ 'invalid')
+
class FloatField(forms.FloatField):
"""
@@ -71,14 +65,17 @@ class FloatField(forms.FloatField):
value = value.replace(',', '.').replace('%', '')
return super(FloatField, self).clean(value)
+
class FinalForm(forms.Form):
final = True
form_label = _(u"Confirm")
+
class FinalDeleteForm(FinalForm):
confirm_msg = " "
confirm_end_msg = _(u"Are you sure you want to delete?")
+
class FormSet(BaseFormSet):
def check_duplicate(self, key_names, error_msg=""):
"""Check for duplicate items in the formset"""
@@ -91,7 +88,8 @@ class FormSet(BaseFormSet):
form = self.forms[i]
if not form.is_valid():
continue
- item = [key_name in form.cleaned_data and form.cleaned_data[key_name]
+ item = [key_name in form.cleaned_data and
+ form.cleaned_data[key_name]
for key_name in key_names]
if not [v for v in item if v]:
continue
@@ -104,6 +102,7 @@ class FormSet(BaseFormSet):
form.fields[DELETION_FIELD_NAME].label = ''
form.fields[DELETION_FIELD_NAME].widget = widgets.DeleteWidget()
+
class TableSelect(forms.Form):
def __init__(self, *args, **kwargs):
super(TableSelect, self).__init__(*args, **kwargs)
@@ -113,19 +112,23 @@ class TableSelect(forms.Form):
def get_input_ids(self):
return self.fields.keys()
+
def get_now():
format = formats.get_format('DATE_INPUT_FORMATS')[0]
value = datetime.datetime.now().strftime(format)
return value
+
class ClosingDateFormSelection(forms.Form):
form_label = _("Closing date")
end_date = forms.DateField(label=_(u"Closing date"),
widget=widgets.JQueryDate)
-def get_form_selection(class_name, label, key, model, base_form, get_url,
- not_selected_error=_(u"You should select an item."), new=False,
- new_message=_(u"Add a new item")):
+
+def get_form_selection(
+ class_name, label, key, model, base_form, get_url,
+ not_selected_error=_(u"You should select an item."), new=False,
+ new_message=_(u"Add a new item")):
"""
Generate a class selection form
class_name -- name of the class
@@ -137,15 +140,17 @@ def get_form_selection(class_name, label, key, model, base_form, get_url,
new -- can add new items
new_message -- message of link to add new items
"""
- attrs = {'_main_key':key,
- '_not_selected_error':not_selected_error,
- 'form_label':label,
- 'associated_models':{key:model},
- 'currents':{key:model},}
- attrs[key] = forms.IntegerField(label="", required=False,
+ attrs = {'_main_key': key,
+ '_not_selected_error': not_selected_error,
+ 'form_label': label,
+ 'associated_models': {key: model},
+ 'currents': {key: model}}
+ attrs[key] = forms.IntegerField(
+ label="", required=False,
validators=[models.valid_id(model)],
widget=widgets.JQueryJqGrid(reverse_lazy(get_url), base_form, model,
new=new, new_message=new_message))
+
def clean(self):
cleaned_data = self.cleaned_data
if self._main_key not in cleaned_data \
@@ -155,19 +160,21 @@ def get_form_selection(class_name, label, key, model, base_form, get_url,
attrs['clean'] = clean
return type(class_name, (forms.Form,), attrs)
+
class DocumentGenerationForm(forms.Form):
"""
Form to generate document by choosing the template
"""
- _associated_model = None # ex: AdministrativeAct
- _associated_object_name = '' # ex: 'archaeological_operations.models.AdministrativeAct'
+ _associated_model = None # ex: AdministrativeAct
+ # ex: 'archaeological_operations.models.AdministrativeAct'
+ _associated_object_name = ''
document_template = forms.ChoiceField(label=_("Template"), choices=[])
def __init__(self, *args, **kwargs):
super(DocumentGenerationForm, self).__init__(*args, **kwargs)
self.fields['document_template'].choices = \
- models.DocumentTemplate.get_tuples(
- dct={'associated_object_name':self._associated_object_name})
+ models.DocumentTemplate.get_tuples(
+ dct={'associated_object_name': self._associated_object_name})
def save(self, object_pk):
try:
@@ -176,7 +183,7 @@ class DocumentGenerationForm(forms.Form):
return
try:
template = models.DocumentTemplate.objects.get(
- pk=self.cleaned_data.get('document_template'))
+ pk=self.cleaned_data.get('document_template'))
except models.DocumentTemplate.DoesNotExist:
return
return template.publish(c_object)
diff --git a/ishtar_common/forms_common.py b/ishtar_common/forms_common.py
index 509b9fbc5..b2aa565bb 100644
--- a/ishtar_common/forms_common.py
+++ b/ishtar_common/forms_common.py
@@ -20,19 +20,14 @@
"""
Administrative forms definitions: manage accounts and persons
"""
-import datetime
from django import forms
from django.conf import settings
from django.contrib.auth.models import User
-from django.contrib.sites.models import Site
from django.core import validators
-from django.core.exceptions import ObjectDoesNotExist, ValidationError
-from django.core.mail import send_mail
-from django.forms.formsets import formset_factory, DELETION_FIELD_NAME
+from django.core.exceptions import ObjectDoesNotExist
+from django.forms.formsets import formset_factory
from django.forms.models import BaseModelFormSet
-from django.template import Context, RequestContext, loader
-from django.shortcuts import render_to_response
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _
@@ -40,27 +35,33 @@ import models
import widgets
from forms import FinalForm, FormSet, reverse_lazy, name_validator, TableSelect
+
def get_town_field(label=_(u"Town"), required=True):
- help_text = _(u"<p>Type name, department code and/or postal code of the "
- u"town you would like to select. The search is insensitive to case.</p>\n"
- u"<p>Only the first twenty results are displayed but specifying the "
- u"department code is generally sufficient to get the appropriate result.</p>"
- u"\n<p class='example'>For instance type \"saint denis 93\" for getting "
- u"the french town Saint-Denis in the Seine-Saint-Denis department.</p>")
+ help_text = _(
+ u"<p>Type name, department code and/or postal code of the "
+ u"town you would like to select. The search is insensitive to case."
+ u"</p>\n<p>Only the first twenty results are displayed but specifying "
+ u"the department code is generally sufficient to get the appropriate "
+ u"result.</p>\n<p class='example'>For instance type \"saint denis 93\""
+ u" for getting the french town Saint-Denis in the Seine-Saint-Denis "
+ u"department.</p>")
# !FIXME hard_link, reverse_lazy doen't seem to work with formsets
return forms.IntegerField(
- widget=widgets.JQueryAutoComplete("/" + settings.URL_PATH + \
- 'autocomplete-town', associated_model=models.Town),
- validators=[models.valid_id(models.Town)], label=label,
- help_text=mark_safe(help_text), required=required)
+ widget=widgets.JQueryAutoComplete(
+ "/" + settings.URL_PATH + 'autocomplete-town',
+ associated_model=models.Town),
+ validators=[models.valid_id(models.Town)], label=label,
+ help_text=mark_safe(help_text), required=required)
+
def get_advanced_town_field(label=_(u"Town"), required=True):
# !FIXME hard_link, reverse_lazy doen't seem to work with formsets
return forms.IntegerField(
- widget=widgets.JQueryTown("/" + settings.URL_PATH + \
- 'autocomplete-advanced-town'),
- validators=[models.valid_id(models.Town)], label=label,
- required=required)
+ widget=widgets.JQueryTown(
+ "/" + settings.URL_PATH + 'autocomplete-advanced-town'),
+ validators=[models.valid_id(models.Town)], label=label,
+ required=required)
+
def get_person_field(label=_(u"Person"), required=True, person_types=[]):
# !FIXME hard_link, reverse_lazy doen't seem to work with formsets
@@ -69,12 +70,13 @@ def get_person_field(label=_(u"Person"), required=True, person_types=[]):
if person_types:
person_types = [
unicode(models.PersonType.objects.get(txt_idx=person_type).pk)
- for person_type in person_types]
+ for person_type in person_types]
url += u"/" + u'_'.join(person_types)
widget = widgets.JQueryAutoComplete(url, associated_model=models.Person)
return forms.IntegerField(widget=widget, label=label, required=required,
validators=[models.valid_id(models.Person)])
+
class NewItemForm(forms.Form):
def __init__(self, *args, **kwargs):
self.limits = {}
@@ -97,6 +99,7 @@ class NewItemForm(forms.Form):
if len(new_choices) == 1:
self.fields[key].initial = [new_choices[0][0]]
+
class NewImportForm(forms.ModelForm):
class Meta:
model = models.Import
@@ -106,12 +109,13 @@ class NewImportForm(forms.ModelForm):
self.instance.user = user
return super(NewImportForm, self).save(commit)
+
class TargetKeyForm(forms.ModelForm):
class Meta:
model = models.TargetKey
fields = ('target', 'key', 'value')
widgets = {
- 'key': forms.TextInput(attrs={'readonly':'readonly'}),
+ 'key': forms.TextInput(attrs={'readonly': 'readonly'}),
'value': forms.Select(),
}
@@ -121,7 +125,8 @@ class TargetKeyForm(forms.ModelForm):
if instance and instance.pk:
self.fields['target'].widget.attrs['readonly'] = True
self.fields['key'].widget.attrs['readonly'] = True
- self.fields['value'].widget.choices = list(instance.target.get_choices())
+ self.fields['value'].widget.choices = list(
+ instance.target.get_choices())
self.fields['key'].required = False
self.fields['value'].required = False
@@ -146,11 +151,12 @@ class TargetKeyForm(forms.ModelForm):
self.associated_import = None
self.instance.save()
+
class OrganizationForm(NewItemForm):
form_label = _(u"Organization")
- associated_models = {'organization_type':models.OrganizationType}
- name = forms.CharField(label=_(u"Name"), max_length=300,
- validators=[name_validator])
+ associated_models = {'organization_type': models.OrganizationType}
+ name = forms.CharField(
+ label=_(u"Name"), max_length=300, validators=[name_validator])
organization_type = forms.ChoiceField(label=_(u"Organization type"),
choices=[])
address = forms.CharField(label=_(u"Address"), widget=forms.Textarea,
@@ -170,20 +176,21 @@ class OrganizationForm(NewItemForm):
def __init__(self, *args, **kwargs):
super(OrganizationForm, self).__init__(*args, **kwargs)
self.fields['organization_type'].choices = \
- models.OrganizationType.get_types()
+ models.OrganizationType.get_types()
self.fields['organization_type'].help_text = \
- models.OrganizationType.get_help()
+ models.OrganizationType.get_help()
self.limit_fields()
def save(self, user):
dct = self.cleaned_data
dct['history_modifier'] = user
dct['organization_type'] = models.OrganizationType.objects.get(
- pk=dct['organization_type'])
+ pk=dct['organization_type'])
new_item = models.Organization(**dct)
new_item.save()
return new_item
+
class OrganizationSelect(TableSelect):
name = forms.CharField(label=_(u"Name"), max_length=300)
organization_type = forms.ChoiceField(label=_(u"Type"), choices=[])
@@ -191,56 +198,65 @@ class OrganizationSelect(TableSelect):
def __init__(self, *args, **kwargs):
super(OrganizationSelect, self).__init__(*args, **kwargs)
self.fields['organization_type'].choices = \
- models.OrganizationType.get_types()
+ models.OrganizationType.get_types()
+
class OrganizationFormSelection(forms.Form):
form_label = _(u"Organization search")
- associated_models = {'pk':models.Organization}
- currents = {'pk':models.Organization}
- pk = forms.IntegerField(label="",
- widget=widgets.JQueryJqGrid(reverse_lazy('get-organization'),
- OrganizationSelect, models.Organization),
- validators=[models.valid_id(models.Organization)])
+ associated_models = {'pk': models.Organization}
+ currents = {'pk': models.Organization}
+ pk = forms.IntegerField(
+ label="",
+ widget=widgets.JQueryJqGrid(reverse_lazy('get-organization'),
+ OrganizationSelect, models.Organization),
+ validators=[models.valid_id(models.Organization)])
+
class BaseOrganizationForm(forms.ModelForm):
form_prefix = "orga"
+
class Meta:
model = models.Organization
fields = ['name', 'organization_type', 'address', 'address_complement',
- 'town', 'postal_code',]
+ 'town', 'postal_code']
+
class PersonSelect(TableSelect):
name = forms.CharField(label=_(u"Name"), max_length=30)
surname = forms.CharField(label=_(u"Surname"), max_length=20)
email = forms.CharField(label=_(u"Email"), max_length=75)
person_types = forms.ChoiceField(label=_(u"Type"), choices=[])
- attached_to = forms.IntegerField(label=_("Organization"),
- widget=widgets.JQueryAutoComplete(
- reverse_lazy('autocomplete-organization'),
- associated_model=models.Organization),
- validators=[models.valid_id(models.Organization)])
+ attached_to = forms.IntegerField(
+ label=_("Organization"),
+ widget=widgets.JQueryAutoComplete(
+ reverse_lazy('autocomplete-organization'),
+ associated_model=models.Organization),
+ validators=[models.valid_id(models.Organization)])
def __init__(self, *args, **kwargs):
super(PersonSelect, self).__init__(*args, **kwargs)
self.fields['person_types'].choices = models.PersonType.get_types()
+
class PersonFormSelection(forms.Form):
form_label = _(u"Person search")
- associated_models = {'pk':models.Person}
- currents = {'pk':models.Person}
- pk = forms.IntegerField(label="",
- widget=widgets.JQueryJqGrid(reverse_lazy('get-person'),
- PersonSelect, models.Person),
- validators=[models.valid_id(models.Person)])
+ associated_models = {'pk': models.Person}
+ currents = {'pk': models.Person}
+ pk = forms.IntegerField(
+ label="",
+ widget=widgets.JQueryJqGrid(reverse_lazy('get-person'),
+ PersonSelect, models.Person),
+ validators=[models.valid_id(models.Person)])
+
class SimplePersonForm(NewItemForm):
form_label = _("Identity")
- associated_models = {'attached_to':models.Organization}
+ associated_models = {'attached_to': models.Organization}
title = forms.ChoiceField(label=_("Title"), choices=models.Person.TYPE)
surname = forms.CharField(label=_(u"Surname"), max_length=20,
validators=[name_validator])
name = forms.CharField(label=_(u"Name"), max_length=30,
- validators=[name_validator])
+ validators=[name_validator])
address = forms.CharField(label=_(u"Address"), widget=forms.Textarea,
required=False)
address_complement = forms.CharField(label=_(u"Address complement"),
@@ -254,28 +270,31 @@ class SimplePersonForm(NewItemForm):
phone = forms.CharField(label=_(u"Phone"), max_length=18, required=False)
mobile_phone = forms.CharField(label=_(u"Town"), max_length=18,
required=False)
- attached_to = forms.IntegerField(label=_("Current organization"),
+ attached_to = forms.IntegerField(
+ label=_("Current organization"),
widget=widgets.JQueryAutoComplete(
- reverse_lazy('autocomplete-organization'),
- associated_model=models.Organization, new=True),
+ reverse_lazy('autocomplete-organization'),
+ associated_model=models.Organization, new=True),
validators=[models.valid_id(models.Organization)], required=False)
+
class BasePersonForm(forms.ModelForm):
class Meta:
model = models.Person
fields = ['title', 'name', 'surname', 'address', 'address_complement',
'town', 'postal_code']
+
class BaseOrganizationPersonForm(forms.ModelForm):
class Meta:
model = models.Person
- fields = ['attached_to', 'title', 'name', 'surname',]
- widgets = {'attached_to':widgets.JQueryPersonOrganization(
- reverse_lazy('autocomplete-organization'),
- reverse_lazy('organization_create'),
- model=models.Organization,
- attrs={'hidden':True},
- new=True),
+ fields = ['attached_to', 'title', 'name', 'surname']
+ widgets = {'attached_to': widgets.JQueryPersonOrganization(
+ reverse_lazy('autocomplete-organization'),
+ reverse_lazy('organization_create'),
+ model=models.Organization,
+ attrs={'hidden': True},
+ new=True),
}
def __init__(self, *args, **kwargs):
@@ -293,14 +312,16 @@ class BaseOrganizationPersonForm(forms.ModelForm):
person.save()
return person
+
class PersonForm(SimplePersonForm):
- person_types = forms.MultipleChoiceField(label=_("Person type"),
- choices=[], widget=forms.CheckboxSelectMultiple)
+ person_types = forms.MultipleChoiceField(
+ label=_("Person type"), choices=[],
+ widget=forms.CheckboxSelectMultiple)
def __init__(self, *args, **kwargs):
super(PersonForm, self).__init__(*args, **kwargs)
self.fields['person_types'].choices = models.PersonType.get_types(
- empty_first=False)
+ empty_first=False)
self.fields['person_types'].help_text = models.PersonType.get_help()
self.limit_fields()
@@ -309,48 +330,58 @@ class PersonForm(SimplePersonForm):
dct['history_modifier'] = user
if 'attached_to' in dct and dct['attached_to']:
dct['attached_to'] = models.Organization.objects.get(
- pk=dct['attached_to'])
+ pk=dct['attached_to'])
person_types = dct.pop('person_types')
new_item = models.Person.objects.create(**dct)
for pt in person_types:
new_item.person_types.add(pt)
return new_item
+
+class NoOrgaPersonForm(PersonForm):
+ def __init__(self, *args, **kwargs):
+ super(NoOrgaPersonForm, self).__init__(*args, **kwargs)
+ self.fields.pop('attached_to')
+
+
class PersonTypeForm(forms.Form):
form_label = _("Person type")
base_model = 'person_type'
- associated_models = {'person_type':models.PersonType}
- person_type = forms.MultipleChoiceField(label=_("Person type"),
- choices=[], widget=forms.CheckboxSelectMultiple)
+ associated_models = {'person_type': models.PersonType}
+ person_type = forms.MultipleChoiceField(
+ label=_("Person type"), choices=[],
+ widget=forms.CheckboxSelectMultiple)
def __init__(self, *args, **kwargs):
super(PersonTypeForm, self).__init__(*args, **kwargs)
self.fields['person_type'].choices = models.PersonType.get_types(
- empty_first=False)
+ empty_first=False)
self.fields['person_type'].help_text = models.PersonType.get_help()
+
class AccountForm(forms.Form):
form_label = _("Account")
- associated_models = {'pk':models.Person}
- currents = {'pk':models.Person}
- pk = forms.IntegerField(label=u"", widget=forms.HiddenInput, required=False)
+ associated_models = {'pk': models.Person}
+ currents = {'pk': models.Person}
+ pk = forms.IntegerField(label=u"", widget=forms.HiddenInput,
+ required=False)
username = forms.CharField(label=_(u"Account"), max_length=30)
email = forms.CharField(label=_(u"Email"), max_length=75,
validators=[validators.validate_email])
- hidden_password = forms.CharField(label=_(u"New password"), max_length=128,
- widget=forms.PasswordInput, required=False,
- validators=[validators.MinLengthValidator(4)])
+ hidden_password = forms.CharField(
+ label=_(u"New password"), max_length=128, widget=forms.PasswordInput,
+ required=False, validators=[validators.MinLengthValidator(4)])
hidden_password_confirm = forms.CharField(
- label=_(u"New password (confirmation)"), max_length=128,
- widget=forms.PasswordInput, required=False)
+ label=_(u"New password (confirmation)"), max_length=128,
+ widget=forms.PasswordInput, required=False)
def __init__(self, *args, **kwargs):
if 'initial' in kwargs and 'pk' in kwargs['initial']:
try:
person = models.Person.objects.get(pk=kwargs['initial']['pk'])
account = models.IshtarUser.objects.get(person=person)
- kwargs['initial'].update({'username':account.username,
- 'email':account.email})
+ kwargs['initial'].update({'username': account.username,
+ 'email': account.email})
except ObjectDoesNotExist:
pass
return super(AccountForm, self).__init__(*args, **kwargs)
@@ -358,23 +389,25 @@ class AccountForm(forms.Form):
def clean(self):
cleaned_data = self.cleaned_data
password = cleaned_data.get("hidden_password")
- if password and password != cleaned_data.get("hidden_password_confirm"):
+ if password and \
+ password != cleaned_data.get("hidden_password_confirm"):
raise forms.ValidationError(_(u"Your password and confirmation "
u"password do not match."))
if not cleaned_data.get("pk"):
models.is_unique(User, 'username')(cleaned_data.get("username"))
if not password:
- raise forms.ValidationError(_(u"You must provide a correct "\
+ raise forms.ValidationError(_(u"You must provide a correct "
u"password."))
# check username unicity
- usernames = models.IshtarUser.objects.filter(username=
- cleaned_data.get('username'))
+ usernames = models.IshtarUser.objects.filter(
+ username=cleaned_data.get('username'))
if cleaned_data.get('pk'):
usernames.exclude(pk=cleaned_data.get('pk'))
if usernames.count():
raise forms.ValidationError(_(u"This username already exists."))
return cleaned_data
+
class FinalAccountForm(forms.Form):
final = True
form_label = _("Confirm")
@@ -385,12 +418,14 @@ class FinalAccountForm(forms.Form):
self.is_hidden = True
return super(FinalAccountForm, self).__init__(*args, **kwargs)
+
class TownForm(forms.Form):
form_label = _("Towns")
base_model = 'town'
- associated_models = {'town':models.Town}
+ associated_models = {'town': models.Town}
town = get_town_field(required=False)
+
class TownFormSet(FormSet):
def clean(self):
"""Checks that no towns are duplicated."""
@@ -400,9 +435,11 @@ class TownFormSet(FormSet):
TownFormset = formset_factory(TownForm, can_delete=True, formset=TownFormSet)
TownFormset.form_label = _("Towns")
+
class MergeFormSet(BaseModelFormSet):
from_key = ''
to_key = ''
+
def __init__(self, *args, **kwargs):
self._cached_list = []
super(MergeFormSet, self).__init__(*args, **kwargs)
@@ -426,11 +463,11 @@ class MergeFormSet(BaseModelFormSet):
if self.is_bound and i < self.initial_form_count():
# Import goes here instead of module-level because importing
# django.db has side effects.
- from django.db import connections
+ # from django.db import connections
pk_key = "%s-%s" % (self.add_prefix(i), self.model._meta.pk.name)
pk = self.data[pk_key]
- pk_field = self.model._meta.pk
- """pk = pk_field.get_db_prep_lookup('exact', pk,
+ """pk_field = self.model._meta.pk
+ pk = pk_field.get_db_prep_lookup('exact', pk,
connection=connections[self.get_queryset().db])"""
pk = self.get_restricted_queryset()[i].pk
if isinstance(pk, list):
@@ -441,7 +478,8 @@ class MergeFormSet(BaseModelFormSet):
if i >= self.initial_form_count() and self.initial_extra:
# Set initial values for extra forms
try:
- kwargs['initial'] = self.initial_extra[i-self.initial_form_count()]
+ kwargs['initial'] = \
+ self.initial_extra[i-self.initial_form_count()]
except IndexError:
pass
return super(BaseModelFormSet, self)._construct_form(i, **kwargs)
@@ -464,8 +502,10 @@ class MergeFormSet(BaseModelFormSet):
self._cached_list = res
return res
+
class MergeForm(forms.ModelForm):
- id = forms.IntegerField(label=u"", widget=forms.HiddenInput, required=False)
+ id = forms.IntegerField(
+ label=u"", widget=forms.HiddenInput, required=False)
a_is_duplicate_b = forms.BooleanField(required=False)
b_is_duplicate_a = forms.BooleanField(required=False)
not_duplicate = forms.BooleanField(required=False)
@@ -492,13 +532,14 @@ class MergeForm(forms.ModelForm):
else:
return
try:
- reverse = self.instance.__class__.objects.get(
- **{self.TO_KEY:from_item,
- self.FROM_KEY:to_item}).delete()
+ self.instance.__class__.objects.get(
+ **{self.TO_KEY: from_item,
+ self.FROM_KEY: to_item}).delete()
except ObjectDoesNotExist:
pass
self.instance.delete()
+
class MergePersonForm(MergeForm):
class Meta:
model = models.Person
@@ -507,6 +548,7 @@ class MergePersonForm(MergeForm):
FROM_KEY = 'from_person'
TO_KEY = 'to_person'
+
class MergeOrganizationForm(MergeForm):
class Meta:
model = models.Organization
@@ -521,12 +563,12 @@ class MergeOrganizationForm(MergeForm):
######################
class SourceForm(forms.Form):
form_label = _(u"Documentation informations")
- associated_models = {'source_type':models.SourceType}
+ associated_models = {'source_type': models.SourceType}
title = forms.CharField(label=_(u"Title"),
validators=[validators.MaxLengthValidator(200)])
source_type = forms.ChoiceField(label=_(u"Source type"), choices=[])
- associated_url = forms.URLField(required=False,
- label=_(u"Numerical ressource (web address)"))
+ associated_url = forms.URLField(
+ required=False, label=_(u"Numerical ressource (web address)"))
receipt_date = forms.DateField(label=_(u"Receipt date"), required=False,
widget=widgets.JQueryDate)
creation_date = forms.DateField(label=_(u"Creation date"), required=False,
@@ -536,12 +578,14 @@ class SourceForm(forms.Form):
super(SourceForm, self).__init__(*args, **kwargs)
self.fields['source_type'].choices = models.SourceType.get_types()
+
class SourceSelect(TableSelect):
authors = forms.IntegerField(
- widget=widgets.JQueryAutoComplete("/" + settings.URL_PATH + \
- 'autocomplete-author', associated_model=models.Author),
- validators=[models.valid_id(models.Author)], label=_(u"Author"),
- required=False)
+ widget=widgets.JQueryAutoComplete(
+ "/" + settings.URL_PATH + 'autocomplete-author',
+ associated_model=models.Author),
+ validators=[models.valid_id(models.Author)], label=_(u"Author"),
+ required=False)
source_type = forms.ChoiceField(label=_("Source type"), choices=[])
@@ -550,6 +594,7 @@ class SourceSelect(TableSelect):
self.fields['source_type'].choices = models.SourceType.get_types()
self.fields['source_type'].help_text = models.SourceType.get_help()
+
class SourceDeletionForm(FinalForm):
confirm_msg = " "
confirm_end_msg = _(u"Would you like to delete this documentation?")
@@ -558,14 +603,16 @@ class SourceDeletionForm(FinalForm):
# Authors management #
######################
+
class AuthorForm(NewItemForm):
form_label = _(u"Author")
- associated_models = {'person':models.Person,
- 'author_type':models.AuthorType}
+ associated_models = {'person': models.Person,
+ 'author_type': models.AuthorType}
person = forms.IntegerField(
- widget=widgets.JQueryAutoComplete("/" + settings.URL_PATH + \
- 'autocomplete-person', associated_model=models.Person, new=True),
- validators=[models.valid_id(models.Person)], label=_(u"Person"))
+ widget=widgets.JQueryAutoComplete(
+ "/" + settings.URL_PATH + 'autocomplete-person',
+ associated_model=models.Person, new=True),
+ validators=[models.valid_id(models.Person)], label=_(u"Person"))
author_type = forms.ChoiceField(label=_(u"Author type"), choices=[])
def __init__(self, *args, **kwargs):
@@ -576,7 +623,7 @@ class AuthorForm(NewItemForm):
def save(self, user):
dct = self.cleaned_data
dct['author_type'] = models.AuthorType.objects.get(
- pk=dct['author_type'])
+ pk=dct['author_type'])
dct['person'] = models.Person.objects.get(pk=dct['person'])
new_item = models.Author(**dct)
new_item.save()
@@ -586,11 +633,13 @@ class AuthorForm(NewItemForm):
class AuthorFormSelection(forms.Form):
form_label = _(u"Author selection")
base_model = 'author'
- associated_models = {'author':models.Author}
+ associated_models = {'author': models.Author}
author = forms.IntegerField(
- widget=widgets.JQueryAutoComplete("/" + settings.URL_PATH + \
- 'autocomplete-author', associated_model=models.Author, new=True),
- validators=[models.valid_id(models.Author)], label=_(u"Author"))
+ widget=widgets.JQueryAutoComplete(
+ "/" + settings.URL_PATH + 'autocomplete-author',
+ associated_model=models.Author, new=True),
+ validators=[models.valid_id(models.Author)], label=_(u"Author"))
+
class AuthorFormSet(FormSet):
def clean(self):
@@ -601,4 +650,3 @@ class AuthorFormSet(FormSet):
AuthorFormset = formset_factory(AuthorFormSelection, can_delete=True,
formset=AuthorFormSet)
AuthorFormset.form_label = _("Authors")
-
diff --git a/ishtar_common/templates/blocks/JQueryAutocomplete.js b/ishtar_common/templates/blocks/JQueryAutocomplete.js
index eb365c38a..038acf1ba 100644
--- a/ishtar_common/templates/blocks/JQueryAutocomplete.js
+++ b/ishtar_common/templates/blocks/JQueryAutocomplete.js
@@ -1,8 +1,13 @@
+{% load replace_underscore %}
+var base_source_{{field_id|replace_underscore}} = {{source}};
+var source_{{field_id|replace_underscore}} = base_source_{{field_id|replace_underscore}};
+
$("#id_select_{{field_id}}").autocomplete({
- source: {{source}},
+ source: source_{{field_id|replace_underscore}},
select: function( event, ui ) {
if(ui.item){
$('#id_{{field_id}}').val(ui.item.id);
+ $('#id_{{field_id}}').change();
} else {
$('#id_{{field_id}}').val(null);
}
@@ -17,3 +22,17 @@ $('#id_select_{{field_id}}').live('click', function(){
$('#id_select_{{field_id}}').val(null);
});
+
+{% if dynamic_limit %}{% for item_id in dynamic_limit %}
+$('#{{item_id}}').change(function(){
+ $("#id_select_{{field_id}}").autocomplete( "option", "source",
+ base_source_{{field_id|replace_underscore}} + $('#{{item_id}}').val()
+ + '/');
+ if ($('#{{item_id}}').val()){
+ $("#id_select_{{field_id}}").prop("disabled", false);
+ } else {
+ $("#id_select_{{field_id}}").prop("disabled", true);
+ }
+});
+$('#{{item_id}}').change();
+{% endfor %}{% endif %}
diff --git a/ishtar_common/templatetags/replace_underscore.py b/ishtar_common/templatetags/replace_underscore.py
index 66931e6fe..d49fcf4fb 100644
--- a/ishtar_common/templatetags/replace_underscore.py
+++ b/ishtar_common/templatetags/replace_underscore.py
@@ -5,6 +5,7 @@ from django.template import Library
register = Library()
+
@register.filter
def replace_underscore(value):
return value.replace('-', '_')
diff --git a/ishtar_common/urls.py b/ishtar_common/urls.py
index bce968b51..eb0fe7ac2 100644
--- a/ishtar_common/urls.py
+++ b/ishtar_common/urls.py
@@ -18,7 +18,7 @@
# See the file COPYING for details.
from django.conf import settings
-from django.conf.urls.defaults import *
+from django.conf.urls.defaults import patterns, include, url
from django.conf.urls.static import static
from menus import menu
@@ -29,53 +29,54 @@ urlpatterns, actions = [], []
# forms
-urlpatterns = patterns('',
- # internationalization
- url(r'^i18n/', include('django.conf.urls.i18n')),
- # General
- url(r'person_search/(?P<step>.+)?$',
- views.person_search_wizard, name='person_search'),
- url(r'person_creation/(?P<step>.+)?$',
- views.person_creation_wizard, name='person_creation'),
- url(r'person_modification/(?P<step>.+)?$',
- views.person_modification_wizard, name='person_modification'),
- url(r'person_deletion/(?P<step>.+)?$',
- views.person_deletion_wizard, name='person_deletion'),
- url(r'^person-edit/$',
- views.PersonCreate.as_view(), name='person_create'),
- url(r'^person-edit/(?P<pk>\d+)$',
- views.PersonEdit.as_view(), name='person_edit'),
- url(r'organization_search/(?P<step>.+)?$',
- views.organization_search_wizard, name='organization_search'),
- url(r'organization_creation/(?P<step>.+)?$',
- views.organization_creation_wizard, name='organization_creation'),
- url(r'organization_modification/(?P<step>.+)?$',
- views.organization_modification_wizard,
- name='organization_modification'),
- url(r'organization_deletion/(?P<step>.+)?$',
- views.organization_deletion_wizard, name='organization_deletion'),
- url(r'organization-edit/$',
- views.OrganizationCreate.as_view(), name='organization_create'),
- url(r'organization-edit/(?P<pk>\d+)$',
- views.OrganizationEdit.as_view(), name='organization_edit'),
- url(r'organization-person-edit/$',
- views.OrganizationPersonCreate.as_view(),
- name='organization_person_create'),
- url(r'organization-person-edit/(?P<pk>\d+)$',
- views.OrganizationPersonEdit.as_view(),
- name='organization_person_edit'),
- url(r'account_management/(?P<step>.+)?$',
- views.account_management_wizard, name='account_management'),
- url(r'^import-new/$', views.NewImportView.as_view(), name='new_import'),
- url(r'^import-list/$', views.ImportListView.as_view(),
- name='current_imports'),
- url(r'^import-list-old/$', views.ImportOldListView.as_view(),
- name='old_imports'),
- url(r'^import-delete/(?P<pk>[0-9]+)/$',
- views.ImportDeleteView.as_view(), name='import_delete'),
- url(r'^import-link-unmatched/(?P<pk>[0-9]+)/$',
- views.ImportLinkView.as_view(), name='import_link_unmatched'),
- )
+urlpatterns = patterns(
+ '',
+ # internationalization
+ url(r'^i18n/', include('django.conf.urls.i18n')),
+ # General
+ url(r'person_search/(?P<step>.+)?$',
+ views.person_search_wizard, name='person_search'),
+ url(r'person_creation/(?P<step>.+)?$',
+ views.person_creation_wizard, name='person_creation'),
+ url(r'person_modification/(?P<step>.+)?$',
+ views.person_modification_wizard, name='person_modification'),
+ url(r'person_deletion/(?P<step>.+)?$',
+ views.person_deletion_wizard, name='person_deletion'),
+ url(r'^person-edit/$',
+ views.PersonCreate.as_view(), name='person_create'),
+ url(r'^person-edit/(?P<pk>\d+)$',
+ views.PersonEdit.as_view(), name='person_edit'),
+ url(r'organization_search/(?P<step>.+)?$',
+ views.organization_search_wizard, name='organization_search'),
+ url(r'organization_creation/(?P<step>.+)?$',
+ views.organization_creation_wizard, name='organization_creation'),
+ url(r'organization_modification/(?P<step>.+)?$',
+ views.organization_modification_wizard,
+ name='organization_modification'),
+ url(r'organization_deletion/(?P<step>.+)?$',
+ views.organization_deletion_wizard, name='organization_deletion'),
+ url(r'organization-edit/$',
+ views.OrganizationCreate.as_view(), name='organization_create'),
+ url(r'organization-edit/(?P<pk>\d+)$',
+ views.OrganizationEdit.as_view(), name='organization_edit'),
+ url(r'organization-person-edit/$',
+ views.OrganizationPersonCreate.as_view(),
+ name='organization_person_create'),
+ url(r'organization-person-edit/(?P<pk>\d+)$',
+ views.OrganizationPersonEdit.as_view(),
+ name='organization_person_edit'),
+ url(r'account_management/(?P<step>.+)?$',
+ views.account_management_wizard, name='account_management'),
+ url(r'^import-new/$', views.NewImportView.as_view(), name='new_import'),
+ url(r'^import-list/$', views.ImportListView.as_view(),
+ name='current_imports'),
+ url(r'^import-list-old/$', views.ImportOldListView.as_view(),
+ name='old_imports'),
+ url(r'^import-delete/(?P<pk>[0-9]+)/$',
+ views.ImportDeleteView.as_view(), name='import_delete'),
+ url(r'^import-link-unmatched/(?P<pk>[0-9]+)/$',
+ views.ImportLinkView.as_view(), name='import_link_unmatched'),
+)
for section in menu.childs:
for menu_item in section.childs:
if hasattr(menu_item, 'childs'):
@@ -86,50 +87,57 @@ for section in menu.childs:
actions = r"|".join(actions)
# other views
-urlpatterns += patterns('ishtar_common.views',
- # General
- url(r'dashboard-main/$', 'dashboard_main',
- name='dashboard-main'),
- url(r'dashboard-main/(?P<item_name>[a-z-]+)/$', 'dashboard_main_detail',
- name='dashboard-main-detail'),
- url(r'update-current-item/$', 'update_current_item',
- name='update-current-item'),
- url(r'new-person/(?:(?P<parent_name>[^/]+)/)?(?:(?P<limits>[^/]+)/)?$',
- 'new_person', name='new-person'),
- url(r'autocomplete-person(?:/([0-9_]+))?/(user)?$', 'autocomplete_person',
- name='autocomplete-person'),
- url(r'get-person/(?P<type>.+)?$', 'get_person',
- name='get-person'),
- url(r'show-person(?:/(?P<pk>.+))?/(?P<type>.+)?$',
- 'show_person', name='show-person'),
- url(r'department-by-state/(?P<state_id>.+)?$', 'department_by_state',
- name='department-by-state'),
- url(r'autocomplete-town/?$', 'autocomplete_town',
- name='autocomplete-town'),
- url(r'autocomplete-advanced-town/(?P<department_id>[0-9]+[ABab]?)?$',
+urlpatterns += patterns(
+ 'ishtar_common.views',
+ # General
+ url(r'dashboard-main/$', 'dashboard_main',
+ name='dashboard-main'),
+ url(r'dashboard-main/(?P<item_name>[a-z-]+)/$', 'dashboard_main_detail',
+ name='dashboard-main-detail'),
+ url(r'update-current-item/$', 'update_current_item',
+ name='update-current-item'),
+ url(r'new-person/(?:(?P<parent_name>[^/]+)/)?(?:(?P<limits>[^/]+)/)?$',
+ 'new_person', name='new-person'),
+ url(r'new-person-noorga/'
+ r'(?:(?P<parent_name>[^/]+)/)?(?:(?P<limits>[^/]+)/)?$',
+ 'new_person_noorga', name='new-person-noorga'),
+ url(r'autocomplete-person(?:/([0-9_]+))?(?:/([0-9_]*))?/(user)?$',
+ 'autocomplete_person', name='autocomplete-person'),
+ url(r'get-person/(?P<type>.+)?$', 'get_person',
+ name='get-person'),
+ url(r'show-person(?:/(?P<pk>.+))?/(?P<type>.+)?$',
+ 'show_person', name='show-person'),
+ url(r'department-by-state/(?P<state_id>.+)?$', 'department_by_state',
+ name='department-by-state'),
+ url(r'autocomplete-town/?$', 'autocomplete_town',
+ name='autocomplete-town'),
+ url(r'autocomplete-advanced-town/(?P<department_id>[0-9]+[ABab]?)?$',
'autocomplete_advanced_town', name='autocomplete-advanced-town'),
- url(r'autocomplete-department/?$', 'autocomplete_department',
- name='autocomplete-department'),
- url(r'new-author/(?:(?P<parent_name>[^/]+)/)?(?:(?P<limits>[^/]+)/)?$',
- 'new_author', name='new-author'),
- url(r'autocomplete-author/$', 'autocomplete_author',
- name='autocomplete-author'),
- url(r'new-organization/(?:(?P<parent_name>[^/]+)/)?(?:(?P<limits>[^/]+)/)?$',
- 'new_organization', name='new-organization'),
- url(r'get-organization/(?P<type>.+)?$', 'get_organization',
- name='get-organization'),
- url(r'show-organization(?:/(?P<pk>.+))?/(?P<type>.+)?$',
- 'show_organization', name='show-organization'),
- url(r'autocomplete-organization/([0-9_]+)?$',
- 'autocomplete_organization', name='autocomplete-organization'),
- url(r'admin-globalvar/', views.GlobalVarEdit.as_view(),
+ url(r'autocomplete-department/?$', 'autocomplete_department',
+ name='autocomplete-department'),
+ url(r'new-author/(?:(?P<parent_name>[^/]+)/)?(?:(?P<limits>[^/]+)/)?$',
+ 'new_author', name='new-author'),
+ url(r'autocomplete-author/$', 'autocomplete_author',
+ name='autocomplete-author'),
+ url(r'new-organization/(?:(?P<parent_name>[^/]+)/)?'
+ r'(?:(?P<limits>[^/]+)/)?$',
+ 'new_organization', name='new-organization'),
+ url(r'get-organization/(?P<type>.+)?$', 'get_organization',
+ name='get-organization'),
+ url(r'show-organization(?:/(?P<pk>.+))?/(?P<type>.+)?$',
+ 'show_organization', name='show-organization'),
+ url(r'autocomplete-organization/([0-9_]+)?$',
+ 'autocomplete_organization', name='autocomplete-organization'),
+ url(r'admin-globalvar/', views.GlobalVarEdit.as_view(),
name='admin-globalvar'),
- url(r'person_merge/(?:(?P<page>\d+)/)?$', 'person_merge', name='person_merge'),
- url(r'organization_merge/(?:(?P<page>\d+)/)?$', 'organization_merge',
- name='organization_merge'),
- url(r'reset/$', 'reset_wizards', name='reset_wizards'),
- url(r'(?P<action_slug>' + actions + r')/$', 'action', name='action'),
+ url(r'person_merge/(?:(?P<page>\d+)/)?$', 'person_merge',
+ name='person_merge'),
+ url(r'organization_merge/(?:(?P<page>\d+)/)?$', 'organization_merge',
+ name='organization_merge'),
+ url(r'reset/$', 'reset_wizards', name='reset_wizards'),
+ url(r'(?P<action_slug>' + actions + r')/$', 'action', name='action'),
)
if settings.DEBUG:
- urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
+ urlpatterns += static(settings.STATIC_URL,
+ document_root=settings.STATIC_ROOT)
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("&nbsp;", "&#160;")
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
diff --git a/ishtar_common/widgets.py b/ishtar_common/widgets.py
index ba7e61e46..efafa38e2 100644
--- a/ishtar_common/widgets.py
+++ b/ishtar_common/widgets.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-# Copyright (C) 2010-2014 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+# Copyright (C) 2010-2015 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
# Copyright (C) 2007 skam <massimo dot scamarcia at gmail.com>
# (http://djangosnippets.org/snippets/233/)
@@ -21,7 +21,7 @@
from django import forms
from django.conf import settings
-from django.core.urlresolvers import resolve, reverse
+from django.core.urlresolvers import reverse
from django.db.models import fields
from django.forms import ClearableFileInput
from django.forms.widgets import flatatt
@@ -44,7 +44,7 @@ class Select2Multiple(forms.SelectMultiple):
css = {
'all': ('select2/css/select2.css',)
}
- js = ('select2/js/select2.min.js',
+ js = ('select2/js/select2.min.js',
'select2/js/init.js')
def render(self, name, value, attrs=None, choices=()):
@@ -54,7 +54,8 @@ class Select2Multiple(forms.SelectMultiple):
attrs = {}
attrs['class'] = klass
return super(Select2Multiple, self).render(name, value, attrs,
- choices)
+ choices)
+
class MultipleAutocompleteField(forms.MultipleChoiceField):
def __init__(self, *args, **kwargs):
@@ -65,10 +66,10 @@ class MultipleAutocompleteField(forms.MultipleChoiceField):
kwargs['choices'] = []
new = kwargs.pop('new') if 'new' in kwargs else None
if 'widget' not in kwargs and self.model:
- kwargs['widget'] = JQueryAutoComplete(reverse_lazy(
- 'autocomplete-'+self.model.__name__.lower()),
- associated_model=self.model, new=new,
- multiple=True)
+ kwargs['widget'] = JQueryAutoComplete(
+ reverse_lazy('autocomplete-'+self.model.__name__.lower()),
+ associated_model=self.model, new=new,
+ multiple=True)
super(MultipleAutocompleteField, self).__init__(*args, **kwargs)
def get_choices(self):
@@ -89,17 +90,18 @@ class MultipleAutocompleteField(forms.MultipleChoiceField):
val = value
value = []
for v in val:
- v = unicode(v).strip('[').strip(']'
- ).strip('u').strip("'").strip('"')
- value += [int(v.strip())
- for v in list(set(v.split(',')))
- if v.strip()]
+ v = unicode(v).strip('[').strip(']')\
+ .strip('u').strip("'").strip('"')
+ value += [int(va.strip())
+ for va in list(set(v.split(',')))
+ if va.strip()]
except (TypeError, ValueError):
value = []
else:
value = []
return super(MultipleAutocompleteField, self).clean(value)
+
class DeleteWidget(forms.CheckboxInput):
def render(self, name, value, attrs=None):
final_attrs = flatatt(self.build_attrs(attrs, name=name,
@@ -109,28 +111,31 @@ class DeleteWidget(forms.CheckboxInput):
output.append('</td></tr>')
return mark_safe('\n'.join(output))
+
class ImageFileInput(ClearableFileInput):
template_with_initial = u'<span class="prettyPhoto">%(initial)s</span>'\
- u' %(clear_template)s<br />%(input_text)s: %(input)s'
+ u' %(clear_template)s<br />%(input_text)s: %(input)s'
+
class SquareMeterWidget(forms.TextInput):
def render(self, name, value, attrs=None):
if not value:
value = u""
final_attrs = flatatt(self.build_attrs(attrs, name=name, value=value))
- dct = {'final_attrs':final_attrs,
- 'unit':settings.SURFACE_UNIT_LABEL,
- 'id':attrs['id'],
- "safe_id":attrs['id'].replace('-', '_')}
+ dct = {'final_attrs': final_attrs,
+ 'unit': settings.SURFACE_UNIT_LABEL,
+ 'id': attrs['id'],
+ "safe_id": attrs['id'].replace('-', '_')}
t = loader.get_template('blocks/SquareMeterWidget.html')
rendered = t.render(Context(dct))
return mark_safe(rendered)
AreaWidget = forms.TextInput
+
if settings.SURFACE_UNIT == 'square-metre':
- #global AreaWidget
AreaWidget = SquareMeterWidget
+
class JQueryDate(forms.TextInput):
def __init__(self, *args, **kwargs):
super(JQueryDate, self).__init__(*args, **kwargs)
@@ -166,12 +171,14 @@ class JQueryDate(forms.TextInput):
}
$(window).load(load_jquerydate_%(var_name)s);
//--></script>
-""" % {"name":name, "var_name":var_name, "country":settings.COUNTRY}
+""" % {"name": name, "var_name": var_name, "country": settings.COUNTRY}
return rendered
+
class JQueryAutoComplete(forms.TextInput):
def __init__(self, source, associated_model=None, options={}, attrs={},
- new=False, multiple=False, limit={}):
+ new=False, url_new='', multiple=False, limit={},
+ dynamic_limit=[]):
"""
Source can be a list containing the autocomplete values or a
string containing the url used for the request.
@@ -184,8 +191,10 @@ class JQueryAutoComplete(forms.TextInput):
self.options = JSONEncoder().encode(options)
self.attrs.update(attrs)
self.new = new
+ self.url_new = url_new
self.multiple = multiple
self.limit = limit
+ self.dynamic_limit = dynamic_limit
def value_from_datadict(self, data, files, name):
if self.multiple:
@@ -203,8 +212,14 @@ class JQueryAutoComplete(forms.TextInput):
source = "'" + unicode(self.source) + "'"
except:
raise ValueError('source type is not valid')
- dct = {'source':mark_safe(source),
- 'field_id':field_id,}
+ dynamic_limit = [
+ 'id_' + lim.replace('_', '') + '-' +
+ '-'.join(field_id.split('-')[1:-1]) + '-' + lim
+ for lim in self.dynamic_limit
+ ]
+ dct = {'source': mark_safe(source),
+ 'field_id': field_id,
+ 'dynamic_limit': dynamic_limit}
if self.options:
dct['options'] = mark_safe('%s' % self.options)
@@ -253,7 +268,7 @@ class JQueryAutoComplete(forms.TextInput):
if hiddens and selects:
attrs_hidden['value'] = hiddens[0]
attrs_select['value'] = selects[0]
- if not self.attrs.has_key('id'):
+ if 'id' not in self.attrs:
attrs_hidden['id'] = 'id_%s' % name
attrs_select['id'] = 'id_select_%s' % name
if 'class' not in attrs_select:
@@ -264,11 +279,14 @@ class JQueryAutoComplete(forms.TextInput):
limits = []
for k in self.limit:
limits.append(k + "__" + "-".join(
- [unicode(v) for v in self.limit[k]]))
+ [unicode(v) for v in self.limit[k]]))
args = [attrs_select['id']]
if limits:
args.append(';'.join(limits))
- url_new = reverse('new-' + model_name, args=args)
+ url_new = 'new-' + model_name
+ if self.url_new:
+ url_new = self.url_new
+ url_new = reverse(url_new, args=args)
new = u' <a href="#" class="add-button" '\
u'onclick="open_window(\'%s\');">+</a>' % url_new
html = u'''<input%(attrs_select)s/>%(new)s\
@@ -276,13 +294,14 @@ class JQueryAutoComplete(forms.TextInput):
<script type="text/javascript"><!--//
$(function() {%(js)s});//--></script>
''' % {
- 'attrs_select' : flatatt(attrs_select),
- 'attrs_hidden' : flatatt(attrs_hidden),
- 'js' : self.render_js(name),
- 'new':new
+ 'attrs_select': flatatt(attrs_select),
+ 'attrs_hidden': flatatt(attrs_hidden),
+ 'js': self.render_js(name),
+ 'new': new
}
return html
+
class JQueryTown(forms.TextInput):
"""
Town fields whith state and department pre-selections
@@ -305,7 +324,7 @@ class JQueryTown(forms.TextInput):
if isinstance(source, list):
encoded_src = JSONEncoder().encode(source)
elif isinstance(source, str) \
- or isinstance(source, unicode):
+ or isinstance(source, unicode):
src = escape(source)
if not src.endswith('/'):
src += "/"
@@ -357,31 +376,32 @@ class JQueryTown(forms.TextInput):
if hiddens and selects:
attrs_hidden['value'] = hiddens[0]
attrs_select['value'] = selects[0]
- if not self.attrs.has_key('id'):
+ if 'id' not in self.attrs:
attrs_hidden['id'] = 'id_%s' % name
attrs_select['id'] = 'id_select_%s' % name
if 'class' not in attrs_select:
attrs_select['class'] = 'autocomplete'
source = self.encode_source(self.source)
- dct = {'source':mark_safe(source),
- 'selected':selected,
- 'safe_field_id':slugify(name).replace('-', '_'),
- 'field_id':name}
+ dct = {'source': mark_safe(source),
+ 'selected': selected,
+ 'safe_field_id': slugify(name).replace('-', '_'),
+ 'field_id': name}
if self.options:
dct['options'] = mark_safe('%s' % self.options)
- dct.update({'attrs_select':mark_safe(flatatt(attrs_select)),
- 'attrs_hidden':mark_safe(flatatt(attrs_hidden)),
- 'name':name,
- 'states':models.State.objects.all().order_by('label'),
- 'selected_department':selected_department,
- 'selected_state':selected_state
- })
- html = loader.get_template('blocks/JQueryAdvancedTown.html').render(
- Context(dct))
+ dct.update({'attrs_select': mark_safe(flatatt(attrs_select)),
+ 'attrs_hidden': mark_safe(flatatt(attrs_hidden)),
+ 'name': name,
+ 'states': models.State.objects.all().order_by('label'),
+ 'selected_department': selected_department,
+ 'selected_state': selected_state}
+ )
+ html = loader.get_template('blocks/JQueryAdvancedTown.html')\
+ .render(Context(dct))
return html
+
class JQueryPersonOrganization(forms.TextInput):
"""
Complex widget which manage:
@@ -392,7 +412,7 @@ class JQueryPersonOrganization(forms.TextInput):
def __init__(self, source, edit_source, model, options={},
attrs={}, new=False, limit={},
- html_template = 'blocks/PersonOrganization.html',
+ html_template='blocks/PersonOrganization.html',
js_template='blocks/JQueryPersonOrganization.js'):
self.options = None
self.attrs = {}
@@ -413,7 +433,7 @@ class JQueryPersonOrganization(forms.TextInput):
if isinstance(source, list):
encoded_src = JSONEncoder().encode(source)
elif isinstance(source, str) \
- or isinstance(source, unicode):
+ or isinstance(source, unicode):
encoded_src = "'%s'" % escape(source)
else:
try:
@@ -425,11 +445,11 @@ class JQueryPersonOrganization(forms.TextInput):
def render_js(self, field_id, selected=''):
source = self.encode_source(self.source)
edit_source = self.encode_source(self.edit_source)
- dct = {'source':mark_safe(source),
- 'edit_source':mark_safe(edit_source),
- 'selected':selected,
- 'safe_field_id':slugify(field_id).replace('-', '_'),
- 'field_id':field_id}
+ dct = {'source': mark_safe(source),
+ 'edit_source': mark_safe(edit_source),
+ 'selected': selected,
+ 'safe_field_id': slugify(field_id).replace('-', '_'),
+ 'field_id': field_id}
if self.options:
dct['options'] = mark_safe('%s' % self.options)
js = loader.get_template(self.js_template).render(Context(dct))
@@ -467,33 +487,33 @@ class JQueryPersonOrganization(forms.TextInput):
if hiddens and selects:
attrs_hidden['value'] = hiddens[0]
attrs_select['value'] = selects[0]
- if not self.attrs.has_key('id'):
+ if 'id' not in self.attrs:
attrs_hidden['id'] = 'id_%s' % name
attrs_select['id'] = 'id_select_%s' % name
if 'class' not in attrs_select:
attrs_select['class'] = 'autocomplete'
new = ''
- dct = {'attrs_select':mark_safe(flatatt(attrs_select)),
- 'attrs_hidden':mark_safe(flatatt(attrs_hidden)),
- 'name':name,
- 'js':self.render_js(name, selected),
- 'new':mark_safe(new)}
+ dct = {'attrs_select': mark_safe(flatatt(attrs_select)),
+ 'attrs_hidden': mark_safe(flatatt(attrs_hidden)),
+ 'name': name,
+ 'js': self.render_js(name, selected),
+ 'new': mark_safe(new)}
html = loader.get_template(self.html_template).render(Context(dct))
return html
+
class JQueryJqGrid(forms.RadioSelect):
COL_TPL = "{name:'%(idx)s', index:'%(idx)s', sortable:true}"
+
class Media:
js = ['%s/js/i18n/grid.locale-%s.js' % (settings.STATIC_URL,
settings.COUNTRY),
- '%s/js/jquery.jqGrid.min.js' % settings.STATIC_URL,
- ]
- css = {'all':['%s/media/ui.jqgrid.css' % settings.STATIC_URL,
- ]}
+ '%s/js/jquery.jqGrid.min.js' % settings.STATIC_URL]
+ css = {'all': ['%s/media/ui.jqgrid.css' % settings.STATIC_URL]}
def __init__(self, source, form, associated_model, attrs={},
- table_cols='TABLE_COLS', multiple=False, multiple_cols=[2], new=False,
- new_message="", source_full=None):
+ table_cols='TABLE_COLS', multiple=False, multiple_cols=[2],
+ new=False, new_message="", source_full=None):
self.source = source
self.form = form
self.attrs = attrs
@@ -507,7 +527,7 @@ class JQueryJqGrid(forms.RadioSelect):
def render(self, name, value=None, attrs=None):
t = loader.get_template('blocks/form_snippet.html')
form = self.form()
- rendered = t.render(Context({'form':form}))
+ rendered = t.render(Context({'form': form}))
dct = {}
if self.new:
model_name = self.associated_model._meta.object_name.lower()
@@ -516,7 +536,6 @@ class JQueryJqGrid(forms.RadioSelect):
extra_cols = []
col_names, col_idx = [], []
for k in form.get_input_ids():
- #field = form.fields[k]
col_idx.append(u'"%s"' % k)
for field_name in getattr(self.associated_model, self.table_cols):
field = self.associated_model
@@ -536,7 +555,7 @@ class JQueryJqGrid(forms.RadioSelect):
else:
continue
col_names.append(u'"%s"' % field_verbose_name)
- extra_cols.append(self.COL_TPL % {'idx':field_name})
+ extra_cols.append(self.COL_TPL % {'idx': field_name})
col_names = col_names and ", ".join(col_names) or ""
col_idx = col_idx and ", ".join(col_idx) or ""
extra_cols = extra_cols and ", ".join(extra_cols) or ""
@@ -544,19 +563,18 @@ class JQueryJqGrid(forms.RadioSelect):
dct['source'] = unicode(self.source)
if unicode(self.source_full) and unicode(self.source_full) != 'None':
dct['source_full'] = unicode(self.source_full)
- dct.update({'name':name,
- 'col_names':col_names,
- 'extra_cols':extra_cols,
- 'source':unicode(self.source),
- 'col_idx':col_idx,
- 'no_result':unicode(_("No results")),
- 'loading':unicode(_("Loading...")),
- 'remove':unicode(_(u"Remove")),
- 'sname':name.replace('-', ''),
- 'multiple':self.multiple,
- 'multi_cols': ",".join((u'"%d"' % col \
- for col in self.multiple_cols))
- })
+ dct.update({'name': name,
+ 'col_names': col_names,
+ 'extra_cols': extra_cols,
+ 'source': unicode(self.source),
+ 'col_idx': col_idx,
+ 'no_result': unicode(_("No results")),
+ 'loading': unicode(_("Loading...")),
+ 'remove': unicode(_(u"Remove")),
+ 'sname': name.replace('-', ''),
+ 'multiple': self.multiple,
+ 'multi_cols': ",".join((u'"%d"' % col
+ for col in self.multiple_cols))})
t = loader.get_template('blocks/JQueryJqGrid.html')
rendered += t.render(Context(dct))
return mark_safe(rendered)
diff --git a/ishtar_common/wizards.py b/ishtar_common/wizards.py
index af236504c..7da654b80 100644
--- a/ishtar_common/wizards.py
+++ b/ishtar_common/wizards.py
@@ -23,13 +23,15 @@ from django.conf import settings
from django.contrib.formtools.wizard.storage import get_storage
from django.contrib.formtools.wizard.views import NamedUrlWizardView, \
normalize_name
+from django.contrib.sites.models import Site
from django.core.exceptions import ObjectDoesNotExist
from django.core.files.images import ImageFile
+from django.core.mail import send_mail
from django.db.models.fields.files import FileField
from django.db.models.fields.related import ManyToManyField
from django.forms import ValidationError
from django.shortcuts import render_to_response
-from django.template import RequestContext
+from django.template import Context, RequestContext, loader
from django.utils.datastructures import MultiValueDict as BaseMultiValueDict
from django.utils.translation import ugettext_lazy as _
import models
@@ -216,12 +218,13 @@ 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.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:
+ 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:
@@ -229,22 +232,22 @@ class Wizard(NamedUrlWizardView):
if not lbl:
continue
value = cleaned_data[key]
- if not value and value != False:
+ if value is None or value == '':
continue
if key in self.translated_keys:
value = _(value)
if type(value) == bool:
- if value == True:
+ if value:
value = _(u"Yes")
- elif value == False:
+ else:
value = _(u"No")
elif key in associated_models:
values = []
if type(value) in (tuple, list):
values = value
elif "," in unicode(value):
- values = unicode(value
- ).strip('[').strip(']').split(",")
+ values = unicode(
+ value).strip('[').strip(']').split(",")
else:
values = [value]
rendered_values = []
@@ -274,7 +277,7 @@ class Wizard(NamedUrlWizardView):
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 {}
+ base_form.associated_models or {}
if hasattr(form, 'forms'):
multi = False
if form.forms:
@@ -289,7 +292,8 @@ class Wizard(NamedUrlWizardView):
multi = len(fields) > 1
if multi:
assert hasattr(frm, 'base_model'), \
- u"Must define a base_model for " + unicode(frm.__class__)
+ u"Must define a base_model for " + \
+ unicode(frm.__class__)
for frm in form.forms:
if not frm.is_valid():
continue
@@ -300,10 +304,11 @@ class Wizard(NamedUrlWizardView):
frm.cleaned_data.pop('DELETE')
for key in frm.cleaned_data:
value = frm.cleaned_data[key]
- if not value and value != False:
+ if value is None or value == '':
continue
if key in associated_models:
- value = associated_models[key].objects.get(pk=value)
+ value = associated_models[key].objects.get(
+ pk=value)
if multi:
vals[key] = value
else:
@@ -319,10 +324,10 @@ class Wizard(NamedUrlWizardView):
if value:
model = associated_models[key]
if isinstance(value, unicode) \
- or isinstance(value, str) and "," in value:
+ or isinstance(value, str) and "," in value:
value = value.split(",")
if isinstance(value, list) \
- or isinstance(value, tuple):
+ or isinstance(value, tuple):
value = [model.objects.get(pk=val)
for val in value if val]
if len(value) == 1:
@@ -346,11 +351,11 @@ class Wizard(NamedUrlWizardView):
return_object)
def get_saved_model(self):
- """Permit a distinguo when saved model is not the base selected model"""
+ "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"""
+ "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,
@@ -363,7 +368,8 @@ class Wizard(NamedUrlWizardView):
if '__' not in k:
continue
vals = k.split('__')
- assert len(vals) == 2, "Only one level of dependant item is managed"
+ 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] = {}
@@ -388,7 +394,7 @@ class Wizard(NamedUrlWizardView):
setattr(obj, k, dct[k])
try:
obj.full_clean()
- except ValidationError, msg:
+ except ValidationError:
return self.render(form_list[-1])
for dependant_item in other_objs:
c_item = getattr(obj, dependant_item)
@@ -429,7 +435,7 @@ class Wizard(NamedUrlWizardView):
obj = self.get_saved_model()(**dct)
try:
obj.full_clean()
- except ValidationError, msg:
+ except ValidationError:
return self.render(form_list[-1])
obj.save()
for k in adds:
@@ -463,13 +469,13 @@ class Wizard(NamedUrlWizardView):
# necessary to manage interaction between models like
# material_index management for baseitems
obj.save()
- dct = {'item':obj}
+ dct = {'item': obj}
# force evaluation of lazy urls
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))
+ context_instance=RequestContext(self.request))
return return_object and (obj, res) or res
def get_deleted(self, keys):
@@ -494,8 +500,6 @@ class Wizard(NamedUrlWizardView):
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:
@@ -513,7 +517,7 @@ class Wizard(NamedUrlWizardView):
if to_delete:
# reorganize
for idx, number in enumerate(sorted(not_to_delete,
- key=lambda x:int(x))):
+ key=lambda x: int(x))):
idx = unicode(idx)
if idx == number:
continue
@@ -527,8 +531,8 @@ class Wizard(NamedUrlWizardView):
frm = form.form
if callable(frm):
frm = frm()
- required_fields = [k for k in frm.fields
- if frm.fields[k].required]
+ required_fields = [ki for ki in frm.fields
+ if frm.fields[ki].required]
base_key = None
if required_fields:
base_key = required_fields[-1]
@@ -538,8 +542,8 @@ class Wizard(NamedUrlWizardView):
total_field = 0
if base_key:
total_field = len([key for key in data.keys()
- if base_key in key.split('-')
- and data[key]])
+ if base_key in key.split('-')
+ and data[key]])
if init and not to_delete and (
not hasattr(self, 'form_initialized') or
not self.form_initialized):
@@ -548,7 +552,8 @@ class Wizard(NamedUrlWizardView):
data[step + u'-TOTAL_FORMS'] = unicode(total_field + 1)
# TODO:remove form_initialized?
# update initialization
- #if request.POST and init and hasattr(self, 'form_initialized') \
+ # if request.POST and init and hasattr(self,
+ # 'form_initialized') \
# and self.form_initialized:
# for k in init[0]:
# data[step + '-' + unicode(total_field) + '-' + k] = \
@@ -560,15 +565,15 @@ class Wizard(NamedUrlWizardView):
if hasattr(form, 'fields') and form.fields.keys():
frm = form
elif hasattr(form, 'extra_form') and hasattr(form.extra_form, 'fields')\
- and form.extra_form.fields.keys():
+ and form.extra_form.fields.keys():
frm = form.extra_form
elif hasattr(form, 'forms') and form.forms \
- and form.forms[0].fields.keys():
+ and form.forms[0].fields.keys():
frm = form.forms[0]
if frm:
first_field = frm.fields[frm.fields.keyOrder[0]]
attrs = first_field.widget.attrs
- attrs.update({'autofocus':"autofocus"})
+ attrs.update({'autofocus': "autofocus"})
first_field.widget.attrs = attrs
return form
@@ -584,10 +589,11 @@ class Wizard(NamedUrlWizardView):
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']:
+ elif 'validate_and_end' in request.POST \
+ and request.POST['validate_and_end']:
last_step = self.steps.last
- new_form = self.get_form(last_step,
+ 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
@@ -668,9 +674,8 @@ class Wizard(NamedUrlWizardView):
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]:
- val = request.session[storage.prefix]['step_data']\
- [form_key][k]
+ request.session[storage.prefix]['step_data'][form_key][k]:
+ val = request.session[storage.prefix]['step_data'][form_key][k]
if type(val) in (list, tuple):
val = val[0]
vals.append(val)
@@ -694,13 +699,13 @@ class Wizard(NamedUrlWizardView):
request = self.request
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()
+ model_name = self.form_list[step]\
+ .associated_models['pk'].__name__.lower()
if step == current_step:
self.storage.reset()
val = model_name in request.session and request.session[model_name]
if val:
- return MultiValueDict({'pk':val})
+ return MultiValueDict({'pk': val})
elif current_obj:
return self.get_instanced_init(current_obj, step)
current_form = self.form_list[current_step]
@@ -709,7 +714,7 @@ class Wizard(NamedUrlWizardView):
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]
+ request.session[model_name]
if val:
initial[key] = val
if initial:
@@ -729,8 +734,8 @@ class Wizard(NamedUrlWizardView):
self.request.session[obj_name] = unicode(obj.pk)
initial = MultiValueDict()
if self.request.POST or \
- (step in self.request.session[self.storage.prefix] and\
- self.request.session[self.storage.prefix]['step_data'][step]):
+ (step in self.request.session[self.storage.prefix] and
+ self.request.session[self.storage.prefix]['step_data'][step]):
return initial
if hasattr(c_form, 'base_fields'):
for base_field in c_form.base_fields.keys():
@@ -738,13 +743,13 @@ class Wizard(NamedUrlWizardView):
if hasattr(c_form, 'base_model') and \
base_field == c_form.base_model:
key = c_form.base_model + 's'
- initial.setlist(base_field, [unicode(val.pk)
- for val in getattr(obj, key).all()])
+ initial.setlist(base_field, [
+ unicode(val.pk) for val in getattr(obj, key).all()])
else:
fields = base_field.split('__')
for field in fields:
if not hasattr(value, field) or \
- getattr(value, field) == None:
+ getattr(value, field) is None:
value = obj
break
value = getattr(value, field)
@@ -762,7 +767,7 @@ class Wizard(NamedUrlWizardView):
isinstance(value, FileField) or \
isinstance(value, ImageFile):
initial[base_field] = value
- elif value != None:
+ elif value is not None:
initial[base_field] = unicode(value)
elif hasattr(c_form, 'management_form'):
initial = []
@@ -789,7 +794,7 @@ class Wizard(NamedUrlWizardView):
value = getattr(child_obj, field)
if hasattr(value, 'pk'):
value = value.pk
- if value != None:
+ if value is not None:
vals[field] = unicode(value)
if vals:
initial.append(vals)
@@ -799,8 +804,9 @@ class Wizard(NamedUrlWizardView):
class SearchWizard(NamedUrlWizardView):
model = None
label = ''
- modification = None # True when the wizard modify an item
- storage_name = 'django.contrib.formtools.wizard.storage.session.SessionStorage'
+ modification = None # True when the wizard modify an item
+ storage_name = \
+ 'django.contrib.formtools.wizard.storage.session.SessionStorage'
def get_wizard_name(self):
"""
@@ -812,7 +818,7 @@ class SearchWizard(NamedUrlWizardView):
"""As the class name can interfere when reused prefix with the url_name
"""
return self.url_name + super(SearchWizard, self).get_prefix(*args,
- **kwargs)
+ **kwargs)
def get_template_names(self):
templates = ['ishtar/wizard/search.html']
@@ -822,8 +828,8 @@ class SearchWizard(NamedUrlWizardView):
context = super(SearchWizard, self).get_context_data(form)
self.request.session['CURRENT_ACTION'] = self.get_wizard_name()
current_step = self.steps.current
- context.update({'current_step':self.form_list[current_step],
- 'wizard_label':self.label})
+ context.update({'current_step': self.form_list[current_step],
+ 'wizard_label': self.label})
return context
@@ -843,7 +849,8 @@ class DeletionWizard(Wizard):
for key in form.cleaned_data:
if key == 'pk':
model = form.associated_models['pk']
- self.current_obj = model.objects.get(pk=form.cleaned_data['pk'])
+ self.current_obj = model.objects.get(
+ pk=form.cleaned_data['pk'])
if not self.current_obj:
return datas
res = {}
@@ -873,8 +880,9 @@ 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_to_response(
+ 'ishtar/wizard/wizard_delete_done.html', {},
+ context_instance=RequestContext(self.request))
class ClosingWizard(Wizard):
@@ -893,7 +901,7 @@ class ClosingWizard(Wizard):
if key == 'pk':
model = form.associated_models['pk']
self.current_obj = model.objects.get(
- pk=form.cleaned_data['pk'])
+ pk=form.cleaned_data['pk'])
if not self.current_obj:
return datas
res = {}
@@ -921,11 +929,13 @@ class ClosingWizard(Wizard):
obj = self.get_current_object()
for form in form_list:
if form.is_valid():
- if 'end_date' in form.cleaned_data and hasattr(obj, 'end_date'):
+ if 'end_date' in form.cleaned_data \
+ 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_to_response(
+ 'ishtar/wizard/wizard_closing_done.html', {},
+ context_instance=RequestContext(self.request))
class PersonWizard(Wizard):
@@ -940,7 +950,7 @@ class PersonDeletionWizard(DeletionWizard):
model = models.Person
fields = model.TABLE_COLS
wizard_templates = {
- 'final-person_deletion':'ishtar/wizard/wizard_person_deletion.html'}
+ 'final-person_deletion': 'ishtar/wizard/wizard_person_deletion.html'}
class OrganizationWizard(Wizard):
@@ -955,12 +965,13 @@ class OrganizationDeletionWizard(DeletionWizard):
model = models.Organization
fields = model.TABLE_COLS
wizard_templates = {
- 'final-organization_deletion':\
- 'ishtar/wizard/wizard_organization_deletion.html'}
+ 'final-organization_deletion':
+ 'ishtar/wizard/wizard_organization_deletion.html'}
class AccountWizard(Wizard):
model = models.Person
+
def get_formated_datas(self, forms):
datas = super(AccountWizard, self).get_formated_datas(forms)
for form in forms:
@@ -980,7 +991,7 @@ class AccountWizard(Wizard):
if not form.is_valid():
return self.render(form)
associated_models = hasattr(form, 'associated_models') and \
- form.associated_models or {}
+ form.associated_models or {}
if type(form.cleaned_data) == dict:
for key in form.cleaned_data:
if key == 'pk':
@@ -1001,10 +1012,11 @@ class AccountWizard(Wizard):
account.email = dct['email']
except ObjectDoesNotExist:
now = datetime.datetime.now()
- account = models.IshtarUser(person=person, username=dct['username'],
- email=dct['email'], first_name=person.surname,
- last_name=person.name, is_staff=False, is_active=True,
- is_superuser=False, last_login=now, date_joined=now)
+ account = models.IshtarUser(
+ person=person, username=dct['username'], email=dct['email'],
+ first_name=person.surname, last_name=person.name,
+ is_staff=False, is_active=True, is_superuser=False,
+ last_login=now, date_joined=now)
if dct['password']:
account.set_password(dct['password'])
account.save()
@@ -1014,20 +1026,21 @@ class AccountWizard(Wizard):
site = Site.objects.get_current()
app_name = site and ("Ishtar - " + site.name) \
- or "Ishtar"
- context = Context({'login':dct['username'],
- 'password':dct['password'],
- 'app_name':app_name,
- 'site': site and site.domain or ""
- })
+ or "Ishtar"
+ 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)
subject = _(u"[%(app_name)s] Account creation/modification") % {
- "app_name":app_name}
+ "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))
+ context_instance=RequestContext(self.request))
return res
def get_form(self, step=None, data=None, files=None):
@@ -1045,6 +1058,7 @@ class AccountWizard(Wizard):
class SourceWizard(Wizard):
model = None
+
def get_extra_model(self, dct, form_list):
dct = super(SourceWizard, self).get_extra_model(dct, form_list)
if 'history_modifier' in dct: