summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@proxience.com>2014-10-29 21:23:16 +0100
committerÉtienne Loks <etienne.loks@proxience.com>2014-10-29 21:26:32 +0100
commit827c268c089cb0591e5adb94cd0d661ef1e71a49 (patch)
tree2f54c1784705b4ec40a9d4bb83e2faa6b7b68fd1
parentebf87a7cc0d21034c387bc2eff85323c63c49680 (diff)
downloadIshtar-827c268c089cb0591e5adb94cd0d661ef1e71a49.tar.bz2
Ishtar-827c268c089cb0591e5adb94cd0d661ef1e71a49.zip
Add global variables (+admin) - implement an easier ooo parsing (refs #2111)
-rw-r--r--example_project/settings.py3
-rw-r--r--ishtar_common/admin.py4
-rw-r--r--ishtar_common/migrations/0010_auto__del_wizardstep__del_wizard__add_globalvar__chg_field_person_atta.py236
-rw-r--r--ishtar_common/models.py52
-rw-r--r--ishtar_common/ooo_replace.py38
-rw-r--r--ishtar_common/tests.py36
-rw-r--r--ishtar_common/tests/test-file.odtbin0 -> 9571 bytes
-rw-r--r--requirements.txt1
8 files changed, 347 insertions, 23 deletions
diff --git a/example_project/settings.py b/example_project/settings.py
index d276ef6bf..27b040874 100644
--- a/example_project/settings.py
+++ b/example_project/settings.py
@@ -121,7 +121,7 @@ INSTALLED_APPS = [
'django.contrib.formtools',
'south',
'registration',
- #'geodjangofla',
+ 'geodjangofla',
'ishtar_common',
'archaeological_operations', # mandatory app to run ishtar
#'django_extensions',
@@ -174,6 +174,7 @@ LOGGING = {'version': 1,
# Ishtar custom
SRID = 27572
ENCODING = 'windows-1252'
+ALT_ENCODING = 'ISO-8859-15'
APP_NAME = "SRA - Pays de la Loire"
SURFACE_UNIT = 'square-metre'
SURFACE_UNIT_LABEL = u'm²'
diff --git a/ishtar_common/admin.py b/ishtar_common/admin.py
index cfbed2f66..9d164a626 100644
--- a/ishtar_common/admin.py
+++ b/ishtar_common/admin.py
@@ -81,6 +81,10 @@ class PersonTypeAdmin(admin.ModelAdmin):
admin.site.register(models.PersonType, PersonTypeAdmin)
+class GlobalVarAdmin(admin.ModelAdmin):
+ list_display = ['slug', 'description', 'value']
+admin.site.register(models.GlobalVar, GlobalVarAdmin)
+
class GeneralTypeAdmin(admin.ModelAdmin):
list_display = ['label', 'txt_idx', 'available']
diff --git a/ishtar_common/migrations/0010_auto__del_wizardstep__del_wizard__add_globalvar__chg_field_person_atta.py b/ishtar_common/migrations/0010_auto__del_wizardstep__del_wizard__add_globalvar__chg_field_person_atta.py
new file mode 100644
index 000000000..4bba74da9
--- /dev/null
+++ b/ishtar_common/migrations/0010_auto__del_wizardstep__del_wizard__add_globalvar__chg_field_person_atta.py
@@ -0,0 +1,236 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+ # Deleting model 'WizardStep'
+ db.delete_table('ishtar_common_wizardstep')
+
+ # Deleting model 'Wizard'
+ db.delete_table('ishtar_common_wizard')
+
+ # Adding model 'GlobalVar'
+ db.create_table('ishtar_common_globalvar', (
+ ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('slug', self.gf('django.db.models.fields.SlugField')(unique=True, max_length=50)),
+ ('description', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),
+ ('value', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),
+ ))
+ db.send_create_signal('ishtar_common', ['GlobalVar'])
+
+
+ # Changing field 'Person.attached_to'
+ db.alter_column('ishtar_common_person', 'attached_to_id', self.gf('django.db.models.fields.related.ForeignKey')(null=True, on_delete=models.SET_NULL, to=orm['ishtar_common.Organization']))
+
+ def backwards(self, orm):
+ # Adding model 'WizardStep'
+ db.create_table('ishtar_common_wizardstep', (
+ ('url_name', self.gf('django.db.models.fields.CharField')(max_length=128)),
+ ('name', self.gf('django.db.models.fields.CharField')(max_length=128)),
+ ('wizard', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['ishtar_common.Wizard'])),
+ ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('order', self.gf('django.db.models.fields.IntegerField')()),
+ ))
+ db.send_create_signal('ishtar_common', ['WizardStep'])
+
+ # Adding model 'Wizard'
+ db.create_table('ishtar_common_wizard', (
+ ('url_name', self.gf('django.db.models.fields.CharField')(max_length=128, unique=True)),
+ ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ))
+ db.send_create_signal('ishtar_common', ['Wizard'])
+
+ # Deleting model 'GlobalVar'
+ db.delete_table('ishtar_common_globalvar')
+
+
+ # Changing field 'Person.attached_to'
+ db.alter_column('ishtar_common_person', 'attached_to_id', self.gf('django.db.models.fields.related.ForeignKey')(null=True, to=orm['ishtar_common.Organization']))
+
+ models = {
+ 'auth.group': {
+ 'Meta': {'object_name': 'Group'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+ },
+ 'auth.permission': {
+ 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'auth.user': {
+ 'Meta': {'object_name': 'User'},
+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'contenttypes.contenttype': {
+ 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+ },
+ 'ishtar_common.arrondissement': {
+ 'Meta': {'object_name': 'Arrondissement'},
+ 'department': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.Department']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '30'})
+ },
+ 'ishtar_common.author': {
+ 'Meta': {'object_name': 'Author'},
+ 'author_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.AuthorType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'person': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'author'", 'to': "orm['ishtar_common.Person']"})
+ },
+ 'ishtar_common.authortype': {
+ 'Meta': {'object_name': 'AuthorType'},
+ 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'comment': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'txt_idx': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'ishtar_common.canton': {
+ 'Meta': {'object_name': 'Canton'},
+ 'arrondissement': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.Arrondissement']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '30'})
+ },
+ 'ishtar_common.department': {
+ 'Meta': {'ordering': "['number']", 'object_name': 'Department'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'label': ('django.db.models.fields.CharField', [], {'max_length': '30'}),
+ 'number': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '3'})
+ },
+ 'ishtar_common.documenttemplate': {
+ 'Meta': {'ordering': "['associated_object_name']", 'object_name': 'DocumentTemplate'},
+ 'associated_object_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'available': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'template': ('django.db.models.fields.files.FileField', [], {'max_length': '100'})
+ },
+ 'ishtar_common.globalvar': {
+ 'Meta': {'ordering': "['slug']", 'object_name': 'GlobalVar'},
+ 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50'}),
+ 'value': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'})
+ },
+ 'ishtar_common.historicalorganization': {
+ 'Meta': {'ordering': "('-history_date', '-history_id')", 'object_name': 'HistoricalOrganization'},
+ 'address': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'address_complement': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'country': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}),
+ 'history_creator_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+ 'history_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ 'history_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'history_modifier_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+ 'history_type': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
+ 'history_user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True'}),
+ 'id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'blank': 'True'}),
+ 'mobile_phone': ('django.db.models.fields.CharField', [], {'max_length': '18', 'null': 'True', 'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '300'}),
+ 'organization_type_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+ 'phone': ('django.db.models.fields.CharField', [], {'max_length': '18', 'null': 'True', 'blank': 'True'}),
+ 'postal_code': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
+ 'town': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'})
+ },
+ 'ishtar_common.ishtaruser': {
+ 'Meta': {'object_name': 'IshtarUser', '_ormbases': ['auth.User']},
+ 'person': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ishtaruser'", 'unique': 'True', 'to': "orm['ishtar_common.Person']"}),
+ 'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'})
+ },
+ 'ishtar_common.organization': {
+ 'Meta': {'object_name': 'Organization'},
+ 'address': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'address_complement': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'country': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}),
+ 'history_creator': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': "orm['auth.User']"}),
+ 'history_modifier': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'to': "orm['auth.User']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'mobile_phone': ('django.db.models.fields.CharField', [], {'max_length': '18', 'null': 'True', 'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '300'}),
+ 'organization_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.OrganizationType']"}),
+ 'phone': ('django.db.models.fields.CharField', [], {'max_length': '18', 'null': 'True', 'blank': 'True'}),
+ 'postal_code': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
+ 'town': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'})
+ },
+ 'ishtar_common.organizationtype': {
+ 'Meta': {'ordering': "('label',)", 'object_name': 'OrganizationType'},
+ 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'comment': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'txt_idx': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'ishtar_common.person': {
+ 'Meta': {'object_name': 'Person'},
+ 'address': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'address_complement': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'attached_to': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'members'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['ishtar_common.Organization']"}),
+ 'country': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}),
+ 'history_creator': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': "orm['auth.User']"}),
+ 'history_modifier': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'to': "orm['auth.User']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'mobile_phone': ('django.db.models.fields.CharField', [], {'max_length': '18', 'null': 'True', 'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '30'}),
+ 'person_types': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['ishtar_common.PersonType']", 'symmetrical': 'False'}),
+ 'phone': ('django.db.models.fields.CharField', [], {'max_length': '18', 'null': 'True', 'blank': 'True'}),
+ 'postal_code': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
+ 'surname': ('django.db.models.fields.CharField', [], {'max_length': '20', 'null': 'True', 'blank': 'True'}),
+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '2'}),
+ 'town': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'})
+ },
+ 'ishtar_common.persontype': {
+ 'Meta': {'ordering': "('label',)", 'object_name': 'PersonType'},
+ 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'comment': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['auth.Group']", 'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'txt_idx': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'ishtar_common.sourcetype': {
+ 'Meta': {'object_name': 'SourceType'},
+ 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'comment': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'txt_idx': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'ishtar_common.town': {
+ 'Meta': {'ordering': "['numero_insee']", 'object_name': 'Town'},
+ 'canton': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.Canton']", 'null': 'True', 'blank': 'True'}),
+ 'center': ('django.contrib.gis.db.models.fields.PointField', [], {'srid': '27572', 'null': 'True', 'blank': 'True'}),
+ 'departement': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.Department']", 'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'numero_insee': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '6'}),
+ 'surface': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'})
+ }
+ }
+
+ complete_apps = ['ishtar_common']
diff --git a/ishtar_common/models.py b/ishtar_common/models.py
index 460612e17..6c4ec2e49 100644
--- a/ishtar_common/models.py
+++ b/ishtar_common/models.py
@@ -28,6 +28,7 @@ import tempfile
import copy
from django.conf import settings
+from django.core.cache import cache
from django.core.exceptions import ObjectDoesNotExist, ValidationError
from django.core.files.uploadedfile import SimpleUploadedFile
from django.core.validators import validate_slug
@@ -45,7 +46,8 @@ from django.contrib import admin
from simple_history.models import HistoricalRecords as BaseHistoricalRecords
-from ooo_replace import ooo_replace
+from ishtar_common.ooo_replace import ooo_replace
+from ishtar_common.utils import get_cache
def post_save_user(sender, **kwargs):
user = kwargs['instance']
@@ -85,6 +87,8 @@ class ValueGetter(object):
values['VALUES'] = u'\n'.join(
[u"%s: %s" % (k, v) for k, v in sorted(value_list,
key=lambda x:x[0])])
+ for global_var in GlobalVar.objects.all():
+ values[global_var.slug] = global_var.value or ""
return values
@classmethod
@@ -525,7 +529,6 @@ class BaseHistorizedItem(models.Model):
items.append('00000000')
return u"-".join([unicode(item) for item in items])
-
class ShortMenuItem(object):
def get_short_menu_class(self):
return ''
@@ -539,26 +542,39 @@ class LightHistorizedItem(BaseHistorizedItem):
super(LightHistorizedItem, self).save(*args, **kwargs)
return True
-class Wizard(models.Model):
- url_name = models.CharField(_(u"URL name"), max_length=128, unique=True)
+class GlobalVar(models.Model):
+ slug = models.SlugField(_(u"Variable name"), unique=True)
+ description = models.TextField(_(u"Description of the variable"),
+ null=True, blank=True)
+ value = models.TextField(_(u"Value"), null=True, blank=True)
class Meta:
- verbose_name = _(u"Wizard")
- ordering = ['url_name']
+ verbose_name = _(u"Global variable")
+ verbose_name_plural = _(u"Global variables")
+ ordering = ['slug']
def __unicode__(self):
- return unicode(self.url_name)
-
-class WizardStep(models.Model):
- order = models.IntegerField(_(u"Order"))
- wizard = models.ForeignKey(Wizard, verbose_name=_(u"Wizard"))
- url_name = models.CharField(_(u"URL name"), max_length=128)
- name = models.CharField(_(u"Label"), max_length=128)
- class Meta:
- verbose_name = _(u"Wizard step")
- ordering = ['wizard', 'order']
+ return unicode(self.slug)
- def __unicode__(self):
- return u"%s » %s" % (unicode(self.wizard), unicode(self.name))
+ @classmethod
+ def get_cache(cls, slug):
+ cache_key, value = get_cache(cls, slug)
+ if value:
+ return value
+ try:
+ obj = cls.objects.get(slug=slug)
+ cache.set(cache_key, obj.value, settings.CACHE_TIMEOUT)
+ return obj.value
+ except cls.DoesNotExist:
+ return None
+
+def cached_globalvar_changed(sender, **kwargs):
+ if not kwargs['instance']:
+ return
+ var = kwargs['instance']
+ cache_key, value = get_cache(GlobalVar, var.slug)
+ cache.set(cache_key, var.value, settings.CACHE_TIMEOUT)
+
+post_save.connect(cached_globalvar_changed, sender=GlobalVar)
class UserDashboard:
def __init__(self):
diff --git a/ishtar_common/ooo_replace.py b/ishtar_common/ooo_replace.py
index 346ef75a4..2fb01724b 100644
--- a/ishtar_common/ooo_replace.py
+++ b/ishtar_common/ooo_replace.py
@@ -17,7 +17,7 @@
# See the file COPYING for details.
-import locale
+import locale, re
from zipfile import ZipFile, ZIP_DEFLATED
from cStringIO import StringIO
from xml.etree.cElementTree import ElementTree, fromstring
@@ -78,9 +78,34 @@ def _format_value(value, default_value):
value = unicode(value) if value else default_value
return value
+VAR_EXPR = u"###VAR %s###"
+RE_VAR = re.compile(u"###VAR %s###" % u"([-a-zA-Z0-9_]+)")
+IF_EXPR = u"###IF %s###(.*)###ENDIF###"
+RE_IF = re.compile(IF_EXPR % u"([-a-zA-Z0-9_]+)")
+
+def _ishtar_parsing(context, value):
+ """
+ ###VAR nom_var### for displaying a variable name
+ ###IF nom_var### ###ENDIF### for conditionnal display
+ Be carreful nested condition are not yet managed!
+ """
+ for key, val in RE_IF.findall(value):
+ v = ""
+ if key in context and context[key]:
+ v = _ishtar_parsing(context, val)
+ value = re.sub(IF_EXPR % key, v, value)
+ for key in RE_VAR.findall(value):
+ v = ""
+ if key in context and context[key]:
+ v = unicode(context[key])
+ value = re.sub(VAR_EXPR % key, v, value)
+ return value
+
def ooo_replace(infile, outfile, context, default_value=''):
inzip = ZipFile(infile, 'r', ZIP_DEFLATED)
outzip = ZipFile(outfile, 'w', ZIP_DEFLATED)
+
+ # regular ooo parsing
content = ElementTree(fromstring(inzip.read('content.xml')))
missing_keys = set()
for xp in ('variable-set', 'variable-get'):
@@ -102,11 +127,16 @@ def ooo_replace(infile, outfile, context, default_value=''):
if value.strip() in context:
value = context[value.strip()]
p.text = value
+
+ # raw content parsing
+ str_io = StringIO()
+ content.write(str_io)
+ value = str_io.getvalue()
+ value = _ishtar_parsing(context, value).encode('utf-8')
+
for f in inzip.infolist():
if f.filename == 'content.xml':
- s = StringIO()
- content.write(s)
- outzip.writestr('content.xml', s.getvalue())
+ outzip.writestr('content.xml', value)
else:
outzip.writestr(f, inzip.read(f.filename))
inzip.close()
diff --git a/ishtar_common/tests.py b/ishtar_common/tests.py
new file mode 100644
index 000000000..cdcb42103
--- /dev/null
+++ b/ishtar_common/tests.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright (C) 2014 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# See the file COPYING for details.
+
+import tempfile
+from zipfile import ZipFile, ZIP_DEFLATED
+
+from django.test import TestCase
+
+from ishtar_common import models, ooo_replace
+from ishtar_common.ooo_replace import ooo_replace
+
+class OOOGenerationTest(TestCase):
+ def testGeneration(self):
+ context = {'test-var':u"Testé", 'test-var2':u""}
+ tmp = tempfile.TemporaryFile()
+ ooo_replace("../ishtar_common/tests/test-file.odt", tmp, context)
+ inzip = ZipFile(tmp, 'r', ZIP_DEFLATED)
+ value = inzip.read('content.xml')
+ self.assertTrue("Testé" in value)
+ self.assertTrue("testé 2" not in value)
diff --git a/ishtar_common/tests/test-file.odt b/ishtar_common/tests/test-file.odt
new file mode 100644
index 000000000..2e73fe0ee
--- /dev/null
+++ b/ishtar_common/tests/test-file.odt
Binary files differ
diff --git a/requirements.txt b/requirements.txt
index 478800dc5..f10f8cdb6 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -8,6 +8,7 @@ pisa==3.0.33
reportlab==2.5
dbf
python-memcached
+unicodecsv
# for xhtml2odt
pytidylib