diff options
author | Étienne Loks <etienne.loks@iggdrasil.net> | 2017-06-30 17:26:44 +0200 |
---|---|---|
committer | Étienne Loks <etienne.loks@iggdrasil.net> | 2017-06-30 17:26:44 +0200 |
commit | 726713f95f91fa83a8e1473625162ae831309952 (patch) | |
tree | 2b8ab152e92a95948e9a038ebcef815bfd56aa38 /ishtar_common | |
parent | fd21739351daf697188329948492c65b1a9bd7e6 (diff) | |
parent | 483fcd46fb60a597959bfde9d00bde4cc1822cd2 (diff) | |
download | Ishtar-726713f95f91fa83a8e1473625162ae831309952.tar.bz2 Ishtar-726713f95f91fa83a8e1473625162ae831309952.zip |
Merge branch 'master' into develop
Diffstat (limited to 'ishtar_common')
-rw-r--r-- | ishtar_common/admin.py | 28 | ||||
-rw-r--r-- | ishtar_common/data_importer.py | 41 | ||||
-rw-r--r-- | ishtar_common/forms_common.py | 1 | ||||
-rw-r--r-- | ishtar_common/locale/django.pot | 626 | ||||
-rw-r--r-- | ishtar_common/management/commands/ishtar_excute_admin_tasks.py | 15 | ||||
-rw-r--r-- | ishtar_common/migrations/0077_auto__add_administrationscript__add_administrationtask.py | 530 | ||||
-rw-r--r-- | ishtar_common/models.py | 124 | ||||
-rw-r--r-- | ishtar_common/templates/blocks/form_snippet.html | 5 | ||||
-rw-r--r-- | ishtar_common/tests.py | 19 |
9 files changed, 1084 insertions, 305 deletions
diff --git a/ishtar_common/admin.py b/ishtar_common/admin.py index cba10ea0d..9f8265033 100644 --- a/ishtar_common/admin.py +++ b/ishtar_common/admin.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -# Copyright (C) 2010-2016 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet> +# Copyright (C) 2010-2017 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet> # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -306,6 +306,32 @@ class ItemKeyAdmin(admin.ModelAdmin): admin.site.register(models.ItemKey, ItemKeyAdmin) +class AdministrationScriptAdmin(admin.ModelAdmin): + list_display = ['name', 'path'] + + def get_readonly_fields(self, request, obj=None): + if obj: + return ('path',) + return [] + +admin.site.register(models.AdministrationScript, AdministrationScriptAdmin) + + +class AdministrationTaskAdmin(admin.ModelAdmin): + readonly_fields = ('state', 'creation_date', 'launch_date', + 'finished_date', "result", ) + list_display = ['script', 'state', 'creation_date', 'launch_date', + 'finished_date', "result"] + list_filter = ['script', 'state'] + + def get_readonly_fields(self, request, obj=None): + if obj: + return ("script", ) + self.readonly_fields + return self.readonly_fields + +admin.site.register(models.AdministrationTask, AdministrationTaskAdmin) + + basic_models = [models.DocumentTemplate, models.IshtarUser] if settings.COUNTRY == 'fr': basic_models += [models.Arrondissement, models.Canton] diff --git a/ishtar_common/data_importer.py b/ishtar_common/data_importer.py index 1fe4ef45c..76b186038 100644 --- a/ishtar_common/data_importer.py +++ b/ishtar_common/data_importer.py @@ -1400,20 +1400,35 @@ class Importer(object): # get all related fields new_created = {} - for attribute in list(data.keys()): - c_c_path = c_path[:] - if not attribute: - data.pop(attribute) - continue - if not data[attribute]: - field_object, model, direct, m2m = \ - cls._meta.get_field_by_name(attribute) - if m2m: + try: + for attribute in list(data.keys()): + c_c_path = c_path[:] + if not attribute: data.pop(attribute) - continue - if attribute != '__force_new': - self.get_field(cls, attribute, data, m2ms, c_c_path, - new_created) + continue + if not data[attribute]: + field_object, model, direct, m2m = \ + cls._meta.get_field_by_name(attribute) + if m2m: + data.pop(attribute) + continue + if attribute != '__force_new': + self.get_field(cls, attribute, data, m2ms, c_c_path, + new_created) + except (ValueError, IntegrityError) as e: + message = e.message + try: + message = e.message.decode('utf-8') + except (UnicodeDecodeError, UnicodeDecodeError): + message = '' + try: + data = unicode(data) + except UnicodeDecodeError: + data = '' + raise ImporterError( + "Erreur d'import %s %s, contexte : %s, erreur : %s" + % (unicode(cls), unicode("__".join(path)), + unicode(data), message)) create_dict = copy.deepcopy(data) for k in create_dict.keys(): diff --git a/ishtar_common/forms_common.py b/ishtar_common/forms_common.py index b317f77e3..61e9f1a88 100644 --- a/ishtar_common/forms_common.py +++ b/ishtar_common/forms_common.py @@ -884,6 +884,7 @@ class AuthorFormSelection(forms.Form): base_model = 'author' associated_models = {'author': models.Author} author = forms.IntegerField( + required=False, widget=widgets.JQueryAutoComplete( "/" + settings.URL_PATH + 'autocomplete-author', associated_model=models.Author, new=True), diff --git a/ishtar_common/locale/django.pot b/ishtar_common/locale/django.pot index 26a06d0b8..4a7e66801 100644 --- a/ishtar_common/locale/django.pot +++ b/ishtar_common/locale/django.pot @@ -120,31 +120,31 @@ msgstr "" msgid "Importer configuration error: field \"{}\" does not exist for {}." msgstr "" -#: data_importer.py:1559 +#: data_importer.py:1574 msgid "line" msgstr "" -#: data_importer.py:1559 +#: data_importer.py:1574 msgid "col" msgstr "" -#: data_importer.py:1559 +#: data_importer.py:1574 msgid "error" msgstr "" -#: data_importer.py:1565 +#: data_importer.py:1580 msgid "field" msgstr "" -#: data_importer.py:1565 +#: data_importer.py:1580 msgid "source" msgstr "" -#: data_importer.py:1565 +#: data_importer.py:1580 msgid "result" msgstr "" -#: data_importer.py:1581 +#: data_importer.py:1596 #, python-format msgid "\"%(value)s\" not in %(values)s" msgstr "" @@ -177,12 +177,12 @@ msgstr "" msgid "Add a new item" msgstr "" -#: forms.py:297 models.py:1556 +#: forms.py:297 models.py:1558 msgid "Template" msgstr "" #: forms_common.py:41 forms_common.py:59 forms_common.py:184 -#: forms_common.py:408 models.py:1622 models.py:3085 +#: forms_common.py:408 models.py:1624 models.py:3087 #: templates/blocks/JQueryAdvancedTown.html:19 #: templates/ishtar/sheet_organization.html:13 msgid "Town" @@ -198,8 +198,8 @@ msgid "" "french town Saint-Denis in the Seine-Saint-Denis department.</p>" msgstr "" -#: forms_common.py:68 forms_common.py:863 ishtar_menu.py:47 models.py:2685 -#: models.py:2878 models.py:2940 templates/ishtar/sheet_person.html:4 +#: forms_common.py:68 forms_common.py:863 ishtar_menu.py:47 models.py:2687 +#: models.py:2880 models.py:2942 templates/ishtar/sheet_person.html:4 msgid "Person" msgstr "" @@ -210,64 +210,65 @@ msgid "" msgstr "" #: forms_common.py:172 forms_common.py:329 forms_common.py:453 -#: ishtar_menu.py:75 models.py:2568 models.py:2659 +#: ishtar_menu.py:75 models.py:2570 models.py:2661 #: templates/ishtar/sheet_organization.html:4 msgid "Organization" msgstr "" #: forms_common.py:175 forms_common.py:212 forms_common.py:324 -#: forms_common.py:378 forms_common.py:448 models.py:1159 models.py:1555 -#: models.py:1824 models.py:1840 models.py:2078 models.py:2356 models.py:2562 -#: models.py:2671 models.py:3071 templates/ishtar/import_list.html:13 +#: forms_common.py:378 forms_common.py:448 models.py:1161 models.py:1557 +#: models.py:1826 models.py:1842 models.py:2080 models.py:2358 models.py:2564 +#: models.py:2673 models.py:3073 models.py:3170 +#: templates/ishtar/import_list.html:13 #: templates/ishtar/sheet_organization.html:8 #: templates/ishtar/sheet_organization.html:21 msgid "Name" msgstr "" -#: forms_common.py:176 models.py:1777 models.py:2209 +#: forms_common.py:176 models.py:1779 models.py:2211 msgid "Organization type" msgstr "" -#: forms_common.py:178 forms_common.py:402 models.py:1617 +#: forms_common.py:178 forms_common.py:402 models.py:1619 #: templates/ishtar/sheet_organization.html:10 msgid "Address" msgstr "" -#: forms_common.py:180 forms_common.py:405 models.py:1618 +#: forms_common.py:180 forms_common.py:405 models.py:1620 #: templates/ishtar/sheet_organization.html:11 msgid "Address complement" msgstr "" -#: forms_common.py:182 forms_common.py:406 models.py:1620 +#: forms_common.py:182 forms_common.py:406 models.py:1622 #: templates/ishtar/sheet_organization.html:12 msgid "Postal code" msgstr "" -#: forms_common.py:185 forms_common.py:409 models.py:1623 +#: forms_common.py:185 forms_common.py:409 models.py:1625 msgid "Country" msgstr "" #: forms_common.py:187 forms_common.py:326 forms_common.py:382 -#: forms_common.py:450 forms_common.py:574 models.py:1650 +#: forms_common.py:450 forms_common.py:574 models.py:1652 msgid "Email" msgstr "" -#: forms_common.py:188 forms_common.py:385 models.py:1635 +#: forms_common.py:188 forms_common.py:385 models.py:1637 #: templates/ishtar/sheet_organization.html:14 #: templates/ishtar/sheet_person.html:21 #: templates/ishtar/wizard/wizard_person.html:17 msgid "Phone" msgstr "" -#: forms_common.py:189 forms_common.py:394 models.py:1647 +#: forms_common.py:189 forms_common.py:394 models.py:1649 #: templates/ishtar/sheet_organization.html:15 #: templates/ishtar/sheet_person.html:39 #: templates/ishtar/wizard/wizard_person.html:35 msgid "Mobile phone" msgstr "" -#: forms_common.py:213 forms_common.py:327 forms_common.py:451 models.py:2247 -#: models.py:2564 models.py:3006 templates/sheet_ope.html:85 +#: forms_common.py:213 forms_common.py:327 forms_common.py:451 models.py:2249 +#: models.py:2566 models.py:3008 templates/sheet_ope.html:85 #: templates/sheet_ope.html.py:105 templates/sheet_ope.html:126 #: templates/ishtar/import_list.html:14 #: templates/ishtar/sheet_organization.html:23 @@ -291,7 +292,7 @@ msgstr "" msgid "Organization to merge" msgstr "" -#: forms_common.py:325 forms_common.py:376 forms_common.py:449 models.py:2669 +#: forms_common.py:325 forms_common.py:376 forms_common.py:449 models.py:2671 #: templates/ishtar/sheet_organization.html:22 msgid "Surname" msgstr "" @@ -309,25 +310,25 @@ msgstr "" msgid "Identity" msgstr "" -#: forms_common.py:373 forms_common.py:781 forms_common.py:830 models.py:2210 -#: models.py:2663 models.py:2665 models.py:3003 templates/sheet_ope.html:104 +#: forms_common.py:373 forms_common.py:781 forms_common.py:830 models.py:2212 +#: models.py:2665 models.py:2667 models.py:3005 templates/sheet_ope.html:104 #: templates/ishtar/blocks/window_tables/documents.html:7 msgid "Title" msgstr "" -#: forms_common.py:374 models.py:2667 +#: forms_common.py:374 models.py:2669 msgid "Salutation" msgstr "" -#: forms_common.py:380 models.py:2673 +#: forms_common.py:380 models.py:2675 msgid "Raw name" msgstr "" -#: forms_common.py:383 models.py:1636 +#: forms_common.py:383 models.py:1638 msgid "Phone description" msgstr "" -#: forms_common.py:386 models.py:1638 models.py:1640 +#: forms_common.py:386 models.py:1640 models.py:1642 msgid "Phone description 2" msgstr "" @@ -335,11 +336,11 @@ msgstr "" msgid "Phone 2" msgstr "" -#: forms_common.py:390 models.py:1644 +#: forms_common.py:390 models.py:1646 msgid "Phone description 3" msgstr "" -#: forms_common.py:392 models.py:1642 +#: forms_common.py:392 models.py:1644 msgid "Phone 3" msgstr "" @@ -347,23 +348,23 @@ msgstr "" msgid "Current organization" msgstr "" -#: forms_common.py:411 models.py:1625 +#: forms_common.py:411 models.py:1627 msgid "Other address: address" msgstr "" -#: forms_common.py:414 models.py:1628 +#: forms_common.py:414 models.py:1630 msgid "Other address: address complement" msgstr "" -#: forms_common.py:416 models.py:1629 +#: forms_common.py:416 models.py:1631 msgid "Other address: postal code" msgstr "" -#: forms_common.py:418 models.py:1631 +#: forms_common.py:418 models.py:1633 msgid "Other address: town" msgstr "" -#: forms_common.py:420 models.py:1633 +#: forms_common.py:420 models.py:1635 msgid "Other address: country" msgstr "" @@ -379,7 +380,7 @@ msgstr "" msgid "Account search" msgstr "" -#: forms_common.py:512 forms_common.py:552 forms_common.py:556 models.py:2616 +#: forms_common.py:512 forms_common.py:552 forms_common.py:556 models.py:2618 msgid "Person type" msgstr "" @@ -411,7 +412,7 @@ msgstr "" msgid "Send the new password by email?" msgstr "" -#: forms_common.py:636 forms_common.py:649 models.py:3086 +#: forms_common.py:636 forms_common.py:649 models.py:3088 msgid "Towns" msgstr "" @@ -427,7 +428,7 @@ msgstr "" msgid "Documentation informations" msgstr "" -#: forms_common.py:783 forms_common.py:831 models.py:2211 models.py:2978 +#: forms_common.py:783 forms_common.py:831 models.py:2213 models.py:2980 msgid "Source type" msgstr "" @@ -439,37 +440,37 @@ msgstr "" msgid "Internal reference" msgstr "" -#: forms_common.py:791 models.py:3017 +#: forms_common.py:791 models.py:3019 msgid "Numerical ressource (web address)" msgstr "" -#: forms_common.py:792 models.py:3019 +#: forms_common.py:792 models.py:3021 msgid "Receipt date" msgstr "" -#: forms_common.py:794 models.py:2382 models.py:3021 +#: forms_common.py:794 models.py:2384 models.py:3023 msgid "Creation date" msgstr "" -#: forms_common.py:797 models.py:3024 +#: forms_common.py:797 models.py:3026 msgid "Receipt date in documentation" msgstr "" -#: forms_common.py:799 forms_common.py:835 models.py:419 models.py:746 -#: models.py:2105 models.py:2677 models.py:3031 +#: forms_common.py:799 forms_common.py:835 models.py:421 models.py:748 +#: models.py:2107 models.py:2679 models.py:3033 msgid "Comment" msgstr "" -#: forms_common.py:801 forms_common.py:834 models.py:1161 models.py:1844 -#: models.py:2032 models.py:2079 models.py:3030 templates/sheet_ope.html:128 +#: forms_common.py:801 forms_common.py:834 models.py:1163 models.py:1846 +#: models.py:2034 models.py:2081 models.py:3032 templates/sheet_ope.html:128 msgid "Description" msgstr "" -#: forms_common.py:804 models.py:3032 +#: forms_common.py:804 models.py:3034 msgid "Additional information" msgstr "" -#: forms_common.py:806 forms_common.py:838 models.py:3034 +#: forms_common.py:806 forms_common.py:838 models.py:3036 msgid "Has a duplicate" msgstr "" @@ -484,7 +485,7 @@ msgid "" "p>" msgstr "" -#: forms_common.py:827 forms_common.py:856 forms_common.py:890 models.py:2945 +#: forms_common.py:827 forms_common.py:856 forms_common.py:890 models.py:2947 #: templates/ishtar/wizard/wizard_person_deletion.html:124 msgid "Author" msgstr "" @@ -497,7 +498,7 @@ msgstr "" msgid "Would you like to delete this documentation?" msgstr "" -#: forms_common.py:864 models.py:2212 models.py:2932 models.py:2942 +#: forms_common.py:864 models.py:2214 models.py:2934 models.py:2944 msgid "Author type" msgstr "" @@ -509,7 +510,7 @@ msgstr "" msgid "There are identical authors." msgstr "" -#: forms_common.py:901 models.py:2946 models.py:3013 +#: forms_common.py:901 models.py:2948 models.py:3015 #: templates/sheet_ope.html:106 #: templates/ishtar/blocks/window_tables/documents.html:9 msgid "Authors" @@ -527,7 +528,7 @@ msgstr "" msgid "Deletion" msgstr "" -#: ishtar_menu.py:39 models.py:1338 views.py:1648 +#: ishtar_menu.py:39 models.py:1340 views.py:1648 msgid "Global variables" msgstr "" @@ -555,7 +556,7 @@ msgstr "" msgid "Manual merge" msgstr "" -#: ishtar_menu.py:109 models.py:2390 +#: ishtar_menu.py:109 models.py:2392 msgid "Imports" msgstr "" @@ -571,280 +572,280 @@ msgstr "" msgid "Old imports" msgstr "" -#: models.py:224 +#: models.py:226 msgid "Not a valid item." msgstr "" -#: models.py:239 +#: models.py:241 msgid "A selected item is not a valid item." msgstr "" -#: models.py:250 +#: models.py:252 msgid "This item already exists." msgstr "" -#: models.py:415 models.py:745 models.py:1590 models.py:1602 models.py:2028 +#: models.py:417 models.py:747 models.py:1592 models.py:1604 models.py:2030 msgid "Label" msgstr "" -#: models.py:417 +#: models.py:419 msgid "Textual ID" msgstr "" -#: models.py:420 models.py:748 models.py:1559 +#: models.py:422 models.py:750 models.py:1561 msgid "Available" msgstr "" -#: models.py:772 models.py:2151 +#: models.py:774 models.py:2153 msgid "Key" msgstr "" -#: models.py:778 +#: models.py:780 msgid "Specific key to an import" msgstr "" -#: models.py:874 +#: models.py:876 msgid "Last editor" msgstr "" -#: models.py:877 +#: models.py:879 msgid "Creator" msgstr "" -#: models.py:1019 models.py:2929 models.py:3097 models.py:3153 +#: models.py:1021 models.py:2931 models.py:3099 models.py:3155 msgid "Order" msgstr "" -#: models.py:1020 +#: models.py:1022 msgid "Symmetrical" msgstr "" -#: models.py:1021 +#: models.py:1023 msgid "Tiny label" msgstr "" -#: models.py:1035 +#: models.py:1037 msgid "Cannot have symmetrical and an inverse_relation" msgstr "" -#: models.py:1151 +#: models.py:1153 msgid "Euro" msgstr "" -#: models.py:1152 +#: models.py:1154 msgid "US dollar" msgstr "" -#: models.py:1153 views.py:1446 views.py:1508 +#: models.py:1155 views.py:1446 views.py:1508 msgid "Operations" msgstr "" -#: models.py:1154 views.py:1448 views.py:1512 +#: models.py:1156 views.py:1448 views.py:1512 msgid "Context records" msgstr "" -#: models.py:1160 models.py:1842 +#: models.py:1162 models.py:1844 msgid "Slug" msgstr "" -#: models.py:1163 +#: models.py:1165 msgid "CSS color code for base module" msgstr "" -#: models.py:1165 +#: models.py:1167 msgid "Files module" msgstr "" -#: models.py:1167 +#: models.py:1169 msgid "CSS color code for files module" msgstr "" -#: models.py:1169 +#: models.py:1171 msgid "Context records module" msgstr "" -#: models.py:1172 +#: models.py:1174 msgid "CSS color code for context record module" msgstr "" -#: models.py:1174 +#: models.py:1176 msgid "Finds module" msgstr "" -#: models.py:1175 +#: models.py:1177 msgid "Need context records module" msgstr "" -#: models.py:1177 +#: models.py:1179 msgid "Find index is based on" msgstr "" -#: models.py:1179 +#: models.py:1181 msgid "" "To prevent irrelevant indexes, change this parameter only if there is no " "find in the database" msgstr "" -#: models.py:1182 +#: models.py:1184 msgid "CSS color code for find module" msgstr "" -#: models.py:1185 +#: models.py:1187 msgid "Warehouses module" msgstr "" -#: models.py:1186 +#: models.py:1188 msgid "Need finds module" msgstr "" -#: models.py:1188 +#: models.py:1190 msgid "CSS code for warehouse module" msgstr "" -#: models.py:1190 +#: models.py:1192 msgid "Mapping module" msgstr "" -#: models.py:1192 +#: models.py:1194 msgid "CSS code for mapping module" msgstr "" -#: models.py:1195 +#: models.py:1197 msgid "Home page" msgstr "" -#: models.py:1196 +#: models.py:1198 #, python-brace-format msgid "" "Homepage of Ishtar - if not defined a default homepage will appear. Use the " "markdown syntax. {random_image} can be used to display a random image." msgstr "" -#: models.py:1200 +#: models.py:1202 msgid "File external id" msgstr "" -#: models.py:1202 +#: models.py:1204 msgid "" "Formula to manage file external ID. Change this with care. With incorrect " "formula, the application might be unusable and import of external data can " "be destructive." msgstr "" -#: models.py:1207 +#: models.py:1209 msgid "Parcel external id" msgstr "" -#: models.py:1210 +#: models.py:1212 msgid "" "Formula to manage parcel external ID. Change this with care. With incorrect " "formula, the application might be unusable and import of external data can " "be destructive." msgstr "" -#: models.py:1215 +#: models.py:1217 msgid "Context record external id" msgstr "" -#: models.py:1217 +#: models.py:1219 msgid "" "Formula to manage context record external ID. Change this with care. With " "incorrect formula, the application might be unusable and import of external " "data can be destructive." msgstr "" -#: models.py:1222 +#: models.py:1224 msgid "Base find external id" msgstr "" -#: models.py:1224 +#: models.py:1226 msgid "" "Formula to manage base find external ID. Change this with care. With " "incorrect formula, the application might be unusable and import of external " "data can be destructive." msgstr "" -#: models.py:1229 +#: models.py:1231 msgid "Find external id" msgstr "" -#: models.py:1231 +#: models.py:1233 msgid "" "Formula to manage find external ID. Change this with care. With incorrect " "formula, the application might be unusable and import of external data can " "be destructive." msgstr "" -#: models.py:1236 +#: models.py:1238 msgid "Container external id" msgstr "" -#: models.py:1238 +#: models.py:1240 msgid "" "Formula to manage container external ID. Change this with care. With " "incorrect formula, the application might be unusable and import of external " "data can be destructive." msgstr "" -#: models.py:1243 +#: models.py:1245 msgid "Warehouse external id" msgstr "" -#: models.py:1245 +#: models.py:1247 msgid "" "Formula to manage warehouse external ID. Change this with care. With " "incorrect formula, the application might be unusable and import of external " "data can be destructive." msgstr "" -#: models.py:1250 +#: models.py:1252 msgid "Raw name for person" msgstr "" -#: models.py:1252 +#: models.py:1254 msgid "" "Formula to manage person raw_name. Change this with care. With incorrect " "formula, the application might be unusable and import of external data can " "be destructive." msgstr "" -#: models.py:1256 +#: models.py:1258 msgid "Current active" msgstr "" -#: models.py:1257 +#: models.py:1259 msgid "Currency" msgstr "" -#: models.py:1261 +#: models.py:1263 msgid "Ishtar site profile" msgstr "" -#: models.py:1262 +#: models.py:1264 msgid "Ishtar site profiles" msgstr "" -#: models.py:1331 +#: models.py:1333 msgid "Variable name" msgstr "" -#: models.py:1332 +#: models.py:1334 msgid "Description of the variable" msgstr "" -#: models.py:1334 models.py:2152 +#: models.py:1336 models.py:2154 msgid "Value" msgstr "" -#: models.py:1337 +#: models.py:1339 msgid "Global variable" msgstr "" -#: models.py:1460 models.py:1490 +#: models.py:1462 models.py:1492 msgid "Total" msgstr "" -#: models.py:1467 models.py:1591 models.py:1603 +#: models.py:1469 models.py:1593 models.py:1605 #: templates/ishtar/sheet_person.html:24 #: templates/ishtar/dashboards/dashboard_main_detail.html:141 #: templates/ishtar/dashboards/dashboard_main_detail_users.html:26 @@ -852,666 +853,725 @@ msgstr "" msgid "Number" msgstr "" -#: models.py:1554 +#: models.py:1556 msgid "Administrative Act" msgstr "" -#: models.py:1558 +#: models.py:1560 msgid "Associated object" msgstr "" -#: models.py:1562 +#: models.py:1564 msgid "Document template" msgstr "" -#: models.py:1563 +#: models.py:1565 msgid "Document templates" msgstr "" -#: models.py:1594 models.py:1604 models.py:2376 +#: models.py:1596 models.py:1606 models.py:2378 models.py:3193 msgid "State" msgstr "" -#: models.py:1608 templates/blocks/JQueryAdvancedTown.html:12 +#: models.py:1610 templates/blocks/JQueryAdvancedTown.html:12 msgid "Department" msgstr "" -#: models.py:1609 +#: models.py:1611 msgid "Departments" msgstr "" -#: models.py:1646 +#: models.py:1648 msgid "Raw phone" msgstr "" -#: models.py:1652 +#: models.py:1654 msgid "Alternative address is prefered" msgstr "" -#: models.py:1691 +#: models.py:1693 msgid "Tel: " msgstr "" -#: models.py:1695 +#: models.py:1697 msgid "Mobile: " msgstr "" -#: models.py:1699 +#: models.py:1701 msgid "Email: " msgstr "" -#: models.py:1704 +#: models.py:1706 msgid "Merge key" msgstr "" -#: models.py:1778 +#: models.py:1780 msgid "Organization types" msgstr "" -#: models.py:1825 +#: models.py:1827 msgid "Class name" msgstr "" -#: models.py:1828 +#: models.py:1830 msgid "Importer - Model" msgstr "" -#: models.py:1829 +#: models.py:1831 msgid "Importer - Models" msgstr "" -#: models.py:1846 templates/ishtar/dashboards/dashboard_main.html:34 +#: models.py:1848 templates/ishtar/dashboards/dashboard_main.html:34 msgid "Users" msgstr "" -#: models.py:1849 +#: models.py:1851 msgid "Associated model" msgstr "" -#: models.py:1852 +#: models.py:1854 msgid "Models that can accept new items" msgstr "" -#: models.py:1853 +#: models.py:1855 msgid "Leave blank for no restrictions" msgstr "" -#: models.py:1855 +#: models.py:1857 msgid "Is template" msgstr "" -#: models.py:1856 +#: models.py:1858 msgid "Unicity keys (separator \";\")" msgstr "" -#: models.py:1860 +#: models.py:1862 msgid "Importer - Type" msgstr "" -#: models.py:1861 +#: models.py:1863 msgid "Importer - Types" msgstr "" -#: models.py:1960 +#: models.py:1962 msgid "Importer - Default" msgstr "" -#: models.py:1961 +#: models.py:1963 msgid "Importer - Defaults" msgstr "" -#: models.py:1996 +#: models.py:1998 msgid "Importer - Default value" msgstr "" -#: models.py:1997 +#: models.py:1999 msgid "Importer - Default values" msgstr "" -#: models.py:2031 +#: models.py:2033 msgid "Column number" msgstr "" -#: models.py:2034 +#: models.py:2036 msgid "Required" msgstr "" -#: models.py:2036 +#: models.py:2038 msgid "Export field name" msgstr "" -#: models.py:2037 +#: models.py:2039 msgid "" "Fill this field if the field name is ambiguous for export. For instance: " "concatenated fields." msgstr "" -#: models.py:2042 +#: models.py:2044 msgid "Importer - Column" msgstr "" -#: models.py:2043 +#: models.py:2045 msgid "Importer - Columns" msgstr "" -#: models.py:2063 +#: models.py:2065 msgid "Field name" msgstr "" -#: models.py:2065 models.py:2099 +#: models.py:2067 models.py:2101 msgid "Force creation of new items" msgstr "" -#: models.py:2067 models.py:2101 +#: models.py:2069 models.py:2103 msgid "Concatenate with existing" msgstr "" -#: models.py:2069 models.py:2103 +#: models.py:2071 models.py:2105 msgid "Concatenate character" msgstr "" -#: models.py:2073 +#: models.py:2075 msgid "Importer - Duplicate field" msgstr "" -#: models.py:2074 +#: models.py:2076 msgid "Importer - Duplicate fields" msgstr "" -#: models.py:2081 +#: models.py:2083 msgid "Regular expression" msgstr "" -#: models.py:2084 +#: models.py:2086 msgid "Importer - Regular expression" msgstr "" -#: models.py:2085 +#: models.py:2087 msgid "Importer - Regular expressions" msgstr "" -#: models.py:2108 +#: models.py:2110 msgid "Importer - Target" msgstr "" -#: models.py:2109 +#: models.py:2111 msgid "Importer - Targets" msgstr "" -#: models.py:2133 views.py:578 +#: models.py:2135 views.py:578 msgid "True" msgstr "" -#: models.py:2134 views.py:580 +#: models.py:2136 views.py:580 msgid "False" msgstr "" -#: models.py:2153 +#: models.py:2155 msgid "Is set" msgstr "" -#: models.py:2160 +#: models.py:2162 msgid "Importer - Target key" msgstr "" -#: models.py:2161 +#: models.py:2163 msgid "Importer - Targets keys" msgstr "" -#: models.py:2213 models.py:3009 +#: models.py:2215 models.py:3011 msgid "Format" msgstr "" -#: models.py:2214 models.py:3101 +#: models.py:2216 models.py:3103 msgid "Operation type" msgstr "" -#: models.py:2215 +#: models.py:2217 msgid "Period" msgstr "" -#: models.py:2216 +#: models.py:2218 msgid "Report state" msgstr "" -#: models.py:2217 +#: models.py:2219 msgid "Remain type" msgstr "" -#: models.py:2218 +#: models.py:2220 msgid "Unit" msgstr "" -#: models.py:2220 +#: models.py:2222 msgid "Activity type" msgstr "" -#: models.py:2221 +#: models.py:2223 msgid "Material" msgstr "" -#: models.py:2223 +#: models.py:2225 msgid "Conservatory state" msgstr "" -#: models.py:2224 +#: models.py:2226 msgid "Container type" msgstr "" -#: models.py:2225 +#: models.py:2227 msgid "Preservation type" msgstr "" -#: models.py:2226 +#: models.py:2228 msgid "Object type" msgstr "" -#: models.py:2227 +#: models.py:2229 msgid "Integrity type" msgstr "" -#: models.py:2229 +#: models.py:2231 msgid "Remarkability type" msgstr "" -#: models.py:2230 +#: models.py:2232 msgid "Batch type" msgstr "" -#: models.py:2232 +#: models.py:2234 msgid "Identification type" msgstr "" -#: models.py:2234 +#: models.py:2236 msgid "Context record relation type" msgstr "" -#: models.py:2235 models.py:3159 +#: models.py:2237 models.py:3161 msgid "Spatial reference system" msgstr "" -#: models.py:2236 models.py:2987 +#: models.py:2238 models.py:2989 msgid "Support type" msgstr "" -#: models.py:2237 models.py:2628 +#: models.py:2239 models.py:2630 msgid "Title type" msgstr "" -#: models.py:2243 +#: models.py:2245 msgid "Integer" msgstr "" -#: models.py:2244 +#: models.py:2246 msgid "Float" msgstr "" -#: models.py:2245 +#: models.py:2247 msgid "String" msgstr "" -#: models.py:2246 templates/sheet_ope.html:86 +#: models.py:2248 templates/sheet_ope.html:86 msgid "Date" msgstr "" -#: models.py:2248 templates/sheet_ope.html:61 templates/sheet_ope.html.py:83 +#: models.py:2250 templates/sheet_ope.html:61 templates/sheet_ope.html.py:83 #: templates/ishtar/dashboards/dashboard_main_detail.html:126 msgid "Year" msgstr "" -#: models.py:2249 +#: models.py:2251 msgid "String to boolean" msgstr "" -#: models.py:2250 +#: models.py:2252 msgctxt "filesystem" msgid "File" msgstr "" -#: models.py:2251 +#: models.py:2253 msgid "Unknow type" msgstr "" -#: models.py:2267 +#: models.py:2269 msgid "4 digit year. e.g.: \"2015\"" msgstr "" -#: models.py:2268 +#: models.py:2270 msgid "4 digit year/month/day. e.g.: \"2015/02/04\"" msgstr "" -#: models.py:2269 +#: models.py:2271 msgid "Day/month/4 digit year. e.g.: \"04/02/2015\"" msgstr "" -#: models.py:2279 +#: models.py:2281 msgid "Options" msgstr "" -#: models.py:2281 +#: models.py:2283 msgid "Split character(s)" msgstr "" -#: models.py:2285 +#: models.py:2287 msgid "Importer - Formater type" msgstr "" -#: models.py:2286 +#: models.py:2288 msgid "Importer - Formater types" msgstr "" -#: models.py:2338 templates/ishtar/dashboards/dashboard_main_detail.html:63 +#: models.py:2340 templates/ishtar/dashboards/dashboard_main_detail.html:63 msgid "Created" msgstr "" -#: models.py:2339 +#: models.py:2341 msgid "Analyse in progress" msgstr "" -#: models.py:2340 +#: models.py:2342 msgid "Analysed" msgstr "" -#: models.py:2341 +#: models.py:2343 msgid "Import pending" msgstr "" -#: models.py:2342 +#: models.py:2344 msgid "Import in progress" msgstr "" -#: models.py:2343 +#: models.py:2345 models.py:3184 msgid "Finished with errors" msgstr "" -#: models.py:2344 +#: models.py:2346 models.py:3185 msgid "Finished" msgstr "" -#: models.py:2345 +#: models.py:2347 msgid "Archived" msgstr "" -#: models.py:2360 +#: models.py:2362 msgid "Imported file" msgstr "" -#: models.py:2362 +#: models.py:2364 msgid "Associated images (zip file)" msgstr "" -#: models.py:2364 +#: models.py:2366 msgid "Encoding" msgstr "" -#: models.py:2366 +#: models.py:2368 msgid "Skip lines" msgstr "" -#: models.py:2367 templates/ishtar/import_list.html:51 +#: models.py:2369 templates/ishtar/import_list.html:51 msgid "Error file" msgstr "" -#: models.py:2370 +#: models.py:2372 msgid "Result file" msgstr "" -#: models.py:2373 templates/ishtar/import_list.html:57 +#: models.py:2375 templates/ishtar/import_list.html:57 msgid "Match file" msgstr "" -#: models.py:2379 +#: models.py:2381 msgid "Conservative import" msgstr "" -#: models.py:2383 +#: models.py:2385 msgid "End date" msgstr "" -#: models.py:2386 +#: models.py:2388 msgid "Remaining seconds" msgstr "" -#: models.py:2389 +#: models.py:2391 msgid "Import" msgstr "" -#: models.py:2418 +#: models.py:2420 msgid "Analyse" msgstr "" -#: models.py:2420 models.py:2423 +#: models.py:2422 models.py:2425 msgid "Re-analyse" msgstr "" -#: models.py:2421 +#: models.py:2423 msgid "Launch import" msgstr "" -#: models.py:2424 +#: models.py:2426 msgid "Re-import" msgstr "" -#: models.py:2425 +#: models.py:2427 msgid "Archive" msgstr "" -#: models.py:2427 +#: models.py:2429 msgid "Unarchive" msgstr "" -#: models.py:2428 widgets.py:198 templates/ishtar/form_delete.html:11 +#: models.py:2430 widgets.py:198 templates/ishtar/form_delete.html:11 msgid "Delete" msgstr "" -#: models.py:2569 +#: models.py:2571 msgid "Organizations" msgstr "" -#: models.py:2571 +#: models.py:2573 msgid "Can view all Organizations" msgstr "" -#: models.py:2572 +#: models.py:2574 msgid "Can view own Organization" msgstr "" -#: models.py:2573 +#: models.py:2575 msgid "Can add own Organization" msgstr "" -#: models.py:2575 +#: models.py:2577 msgid "Can change own Organization" msgstr "" -#: models.py:2577 +#: models.py:2579 msgid "Can delete own Organization" msgstr "" -#: models.py:2612 +#: models.py:2614 msgid "Groups" msgstr "" -#: models.py:2617 +#: models.py:2619 msgid "Person types" msgstr "" -#: models.py:2629 +#: models.py:2631 msgid "Title types" msgstr "" -#: models.py:2638 +#: models.py:2640 msgid "Mr" msgstr "" -#: models.py:2639 +#: models.py:2641 msgid "Miss" msgstr "" -#: models.py:2640 +#: models.py:2642 msgid "Mr and Mrs" msgstr "" -#: models.py:2641 +#: models.py:2643 msgid "Mrs" msgstr "" -#: models.py:2642 +#: models.py:2644 msgid "Doctor" msgstr "" -#: models.py:2675 +#: models.py:2677 msgid "Contact type" msgstr "" -#: models.py:2678 models.py:2742 +#: models.py:2680 models.py:2744 msgid "Types" msgstr "" -#: models.py:2681 +#: models.py:2683 msgid "Is attached to" msgstr "" -#: models.py:2686 +#: models.py:2688 msgid "Persons" msgstr "" -#: models.py:2688 +#: models.py:2690 msgid "Can view all Persons" msgstr "" -#: models.py:2689 +#: models.py:2691 msgid "Can view own Person" msgstr "" -#: models.py:2690 +#: models.py:2692 msgid "Can add own Person" msgstr "" -#: models.py:2691 +#: models.py:2693 msgid "Can change own Person" msgstr "" -#: models.py:2692 +#: models.py:2694 msgid "Can delete own Person" msgstr "" -#: models.py:2881 +#: models.py:2883 msgid "Advanced shortcut menu" msgstr "" -#: models.py:2884 +#: models.py:2886 msgid "Ishtar user" msgstr "" -#: models.py:2885 +#: models.py:2887 msgid "Ishtar users" msgstr "" -#: models.py:2925 +#: models.py:2927 msgid "To modify the password use the form in Auth > User" msgstr "" -#: models.py:2933 +#: models.py:2935 msgid "Author types" msgstr "" -#: models.py:2950 +#: models.py:2952 msgid "Can view all Authors" msgstr "" -#: models.py:2952 +#: models.py:2954 msgid "Can view own Author" msgstr "" -#: models.py:2954 +#: models.py:2956 msgid "Can add own Author" msgstr "" -#: models.py:2956 +#: models.py:2958 msgid "Can change own Author" msgstr "" -#: models.py:2958 +#: models.py:2960 msgid "Can delete own Author" msgstr "" -#: models.py:2979 +#: models.py:2981 msgid "Source types" msgstr "" -#: models.py:2988 +#: models.py:2990 msgid "Support types" msgstr "" -#: models.py:2995 +#: models.py:2997 msgid "Format type" msgstr "" -#: models.py:2996 +#: models.py:2998 msgid "Format types" msgstr "" -#: models.py:3004 +#: models.py:3006 msgid "External ID" msgstr "" -#: models.py:3007 +#: models.py:3009 msgid "Support" msgstr "" -#: models.py:3011 +#: models.py:3013 msgid "Scale" msgstr "" -#: models.py:3025 +#: models.py:3027 msgid "Item number" msgstr "" -#: models.py:3026 +#: models.py:3028 msgid "Ref." msgstr "" -#: models.py:3029 +#: models.py:3031 msgid "Internal ref." msgstr "" -#: models.py:3072 +#: models.py:3074 msgid "Surface (m2)" msgstr "" -#: models.py:3073 templates/sheet_ope.html:46 templates/sheet_ope.html.py:107 +#: models.py:3075 templates/sheet_ope.html:46 templates/sheet_ope.html.py:107 msgid "Localisation" msgstr "" -#: models.py:3098 +#: models.py:3100 msgid "Is preventive" msgstr "" -#: models.py:3102 +#: models.py:3104 msgid "Operation types" msgstr "" -#: models.py:3131 +#: models.py:3133 msgid "Preventive" msgstr "" -#: models.py:3132 +#: models.py:3134 msgid "Research" msgstr "" -#: models.py:3155 +#: models.py:3157 msgid "Authority name" msgstr "" -#: models.py:3156 +#: models.py:3158 msgid "Authority SRID" msgstr "" -#: models.py:3160 +#: models.py:3162 msgid "Spatial reference systems" msgstr "" +#: models.py:3169 +msgid "Filename" +msgstr "" + +#: models.py:3174 +msgid "Administration script" +msgstr "" + +#: models.py:3175 +msgid "Administration scripts" +msgstr "" + +#: models.py:3182 +msgid "Scheduled" +msgstr "" + +#: models.py:3183 +msgid "In progress" +msgstr "" + +#: models.py:3198 +msgid "Result" +msgstr "" + +#: models.py:3201 +msgid "Administration task" +msgstr "" + +#: models.py:3202 +msgid "Administration tasks" +msgstr "" + +#: models.py:3206 +msgid "Unknown" +msgstr "" + +#: models.py:3221 +msgid "" +"ISHTAR_SCRIPT_DIR is not set in your local_settings. Contact your " +"administrator." +msgstr "" + +#: models.py:3230 +msgid "" +"Your ISHTAR_SCRIPT_DIR is containing dots \"..\". As it can refer to " +"relative paths, it can be a security issue and this is not allowed. Only put " +"a full path." +msgstr "" + +#: models.py:3241 +msgid "Your ISHTAR_SCRIPT_DIR: \"{}\" is not a valid directory." +msgstr "" + +#: models.py:3257 +msgid "" +"Script \"{}\" is not available in your script directory. Check your " +"configuration." +msgstr "" + #: utils.py:100 msgid " (...)" msgstr "" diff --git a/ishtar_common/management/commands/ishtar_excute_admin_tasks.py b/ishtar_common/management/commands/ishtar_excute_admin_tasks.py new file mode 100644 index 000000000..3fe66ad3b --- /dev/null +++ b/ishtar_common/management/commands/ishtar_excute_admin_tasks.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from django.core.management.base import BaseCommand, CommandError + +from ishtar_common import models + + +class Command(BaseCommand): + help = "./manage.py ishtar_execute_admin_tasks\n\n"\ + "Launch pending administration tasks." + + def handle(self, *args, **options): + for task in models.AdministrationTask.objects.filter(state='S').all(): + task.execute() diff --git a/ishtar_common/migrations/0077_auto__add_administrationscript__add_administrationtask.py b/ishtar_common/migrations/0077_auto__add_administrationscript__add_administrationtask.py new file mode 100644 index 000000000..b6f2680e6 --- /dev/null +++ b/ishtar_common/migrations/0077_auto__add_administrationscript__add_administrationtask.py @@ -0,0 +1,530 @@ +# -*- 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): + # Adding model 'AdministrationScript' + db.create_table('ishtar_common_administrationscript', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('path', self.gf('django.db.models.fields.CharField')(max_length=30)), + ('name', self.gf('django.db.models.fields.TextField')(null=True, blank=True)), + )) + db.send_create_signal('ishtar_common', ['AdministrationScript']) + + # Adding model 'AdministrationTask' + db.create_table('ishtar_common_administrationtask', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('script', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['ishtar_common.AdministrationScript'])), + ('state', self.gf('django.db.models.fields.CharField')(default='S', max_length=2)), + ('creation_date', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)), + ('launch_date', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)), + ('finished_date', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)), + ('result', self.gf('django.db.models.fields.TextField')(null=True, blank=True)), + )) + db.send_create_signal('ishtar_common', ['AdministrationTask']) + + + def backwards(self, orm): + # Deleting model 'AdministrationScript' + db.delete_table('ishtar_common_administrationscript') + + # Deleting model 'AdministrationTask' + db.delete_table('ishtar_common_administrationtask') + + + 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.administrationscript': { + 'Meta': {'ordering': "['name']", 'object_name': 'AdministrationScript'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'path': ('django.db.models.fields.CharField', [], {'max_length': '30'}) + }, + 'ishtar_common.administrationtask': { + 'Meta': {'ordering': "['script']", 'object_name': 'AdministrationTask'}, + 'creation_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'finished_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'launch_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'result': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'script': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.AdministrationScript']"}), + 'state': ('django.db.models.fields.CharField', [], {'default': "'S'", 'max_length': '2'}) + }, + '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': {'ordering': "('author_type__order', 'person__name')", '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': {'ordering': "['order', 'label']", 'object_name': 'AuthorType'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + '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'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '1'}), + 'txt_idx': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}) + }, + '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'}), + 'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.State']", 'null': 'True', 'blank': 'True'}) + }, + 'ishtar_common.documenttemplate': { + 'Meta': {'ordering': "['associated_object_name', '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.format': { + 'Meta': {'ordering': "['label']", 'object_name': 'Format'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + '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': '100'}) + }, + 'ishtar_common.formatertype': { + 'Meta': {'ordering': "('formater_type', 'options')", 'unique_together': "(('formater_type', 'options', 'many_split'),)", 'object_name': 'FormaterType'}, + 'formater_type': ('django.db.models.fields.CharField', [], {'max_length': '20'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'many_split': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}), + 'options': ('django.db.models.fields.CharField', [], {'max_length': '500', 'null': 'True', 'blank': 'True'}) + }, + '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'}), + 'alt_address': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'alt_address_complement': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'alt_address_is_prefered': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'alt_country': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}), + 'alt_postal_code': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}), + 'alt_town': ('django.db.models.fields.CharField', [], {'max_length': '70', 'null': 'True', 'blank': 'True'}), + 'archived': ('django.db.models.fields.NullBooleanField', [], {'default': 'False', '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': '300', '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'}), + 'merge_key': ('django.db.models.fields.TextField', [], {'null': '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': '500'}), + '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'}), + 'phone2': ('django.db.models.fields.CharField', [], {'max_length': '18', 'null': 'True', 'blank': 'True'}), + 'phone3': ('django.db.models.fields.CharField', [], {'max_length': '18', 'null': 'True', 'blank': 'True'}), + 'phone_desc': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True', 'blank': 'True'}), + 'phone_desc2': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True', 'blank': 'True'}), + 'phone_desc3': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True', 'blank': 'True'}), + 'postal_code': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}), + 'raw_phone': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'town': ('django.db.models.fields.CharField', [], {'max_length': '70', 'null': 'True', 'blank': 'True'}) + }, + 'ishtar_common.historicalperson': { + 'Meta': {'ordering': "('-history_date', '-history_id')", 'object_name': 'HistoricalPerson'}, + 'address': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'address_complement': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'alt_address': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'alt_address_complement': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'alt_address_is_prefered': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'alt_country': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}), + 'alt_postal_code': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}), + 'alt_town': ('django.db.models.fields.CharField', [], {'max_length': '70', 'null': 'True', 'blank': 'True'}), + 'archived': ('django.db.models.fields.NullBooleanField', [], {'default': 'False', 'null': 'True', 'blank': 'True'}), + 'attached_to_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}), + 'comment': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'contact_type': ('django.db.models.fields.CharField', [], {'max_length': '300', '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': '300', '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'}), + 'merge_key': ('django.db.models.fields.TextField', [], {'null': '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': '200', 'null': 'True', 'blank': 'True'}), + 'old_title': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), + 'phone': ('django.db.models.fields.CharField', [], {'max_length': '18', 'null': 'True', 'blank': 'True'}), + 'phone2': ('django.db.models.fields.CharField', [], {'max_length': '18', 'null': 'True', 'blank': 'True'}), + 'phone3': ('django.db.models.fields.CharField', [], {'max_length': '18', 'null': 'True', 'blank': 'True'}), + 'phone_desc': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True', 'blank': 'True'}), + 'phone_desc2': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True', 'blank': 'True'}), + 'phone_desc3': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True', 'blank': 'True'}), + 'postal_code': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}), + 'raw_name': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True', 'blank': 'True'}), + 'raw_phone': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'salutation': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'surname': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), + 'title_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}), + 'town': ('django.db.models.fields.CharField', [], {'max_length': '70', 'null': 'True', 'blank': 'True'}) + }, + 'ishtar_common.import': { + 'Meta': {'object_name': 'Import'}, + 'conservative_import': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'creation_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}), + 'encoding': ('django.db.models.fields.CharField', [], {'default': "'utf-8'", 'max_length': '15'}), + 'end_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'error_file': ('django.db.models.fields.files.FileField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'imported_file': ('django.db.models.fields.files.FileField', [], {'max_length': '220'}), + 'imported_images': ('django.db.models.fields.files.FileField', [], {'max_length': '220', 'null': 'True', 'blank': 'True'}), + 'importer_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.ImporterType']"}), + 'match_file': ('django.db.models.fields.files.FileField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '500', 'null': 'True', 'blank': 'True'}), + 'result_file': ('django.db.models.fields.files.FileField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'seconds_remaining': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'skip_lines': ('django.db.models.fields.IntegerField', [], {'default': '1'}), + 'state': ('django.db.models.fields.CharField', [], {'default': "'C'", 'max_length': '2'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.IshtarUser']"}) + }, + 'ishtar_common.importercolumn': { + 'Meta': {'ordering': "('importer_type', 'col_number')", 'unique_together': "(('importer_type', 'col_number'),)", 'object_name': 'ImporterColumn'}, + 'col_number': ('django.db.models.fields.IntegerField', [], {'default': '1'}), + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'export_field_name': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'importer_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'columns'", 'to': "orm['ishtar_common.ImporterType']"}), + 'label': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'regexp_pre_filter': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.Regexp']", 'null': 'True', 'blank': 'True'}), + 'required': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'ishtar_common.importerdefault': { + 'Meta': {'object_name': 'ImporterDefault'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'importer_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'defaults'", 'to': "orm['ishtar_common.ImporterType']"}), + 'target': ('django.db.models.fields.CharField', [], {'max_length': '500'}) + }, + 'ishtar_common.importerdefaultvalues': { + 'Meta': {'object_name': 'ImporterDefaultValues'}, + 'default_target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'default_values'", 'to': "orm['ishtar_common.ImporterDefault']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'target': ('django.db.models.fields.CharField', [], {'max_length': '500'}), + 'value': ('django.db.models.fields.CharField', [], {'max_length': '500'}) + }, + 'ishtar_common.importerduplicatefield': { + 'Meta': {'object_name': 'ImporterDuplicateField'}, + 'column': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'duplicate_fields'", 'to': "orm['ishtar_common.ImporterColumn']"}), + 'concat': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'concat_str': ('django.db.models.fields.CharField', [], {'max_length': '5', 'null': 'True', 'blank': 'True'}), + 'field_name': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'force_new': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + 'ishtar_common.importermodel': { + 'Meta': {'ordering': "('name',)", 'object_name': 'ImporterModel'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'klass': ('django.db.models.fields.CharField', [], {'max_length': '200'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '200'}) + }, + 'ishtar_common.importertype': { + 'Meta': {'ordering': "('name',)", 'object_name': 'ImporterType'}, + 'associated_models': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': "orm['ishtar_common.ImporterModel']"}), + 'created_models': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['ishtar_common.ImporterModel']"}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '500', 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_template': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '100', 'unique': 'True', 'null': 'True', 'blank': 'True'}), + 'unicity_keys': ('django.db.models.fields.CharField', [], {'max_length': '500', 'null': 'True', 'blank': 'True'}), + 'users': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['ishtar_common.IshtarUser']", 'null': 'True', 'blank': 'True'}) + }, + 'ishtar_common.importtarget': { + 'Meta': {'object_name': 'ImportTarget'}, + 'column': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'targets'", 'to': "orm['ishtar_common.ImporterColumn']"}), + 'comment': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'concat': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'concat_str': ('django.db.models.fields.CharField', [], {'max_length': '5', 'null': 'True', 'blank': 'True'}), + 'force_new': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'formater_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.FormaterType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'regexp_filter': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.Regexp']", 'null': 'True', 'blank': 'True'}), + 'target': ('django.db.models.fields.CharField', [], {'max_length': '500'}) + }, + 'ishtar_common.ishtarsiteprofile': { + 'Meta': {'ordering': "['label']", 'object_name': 'IshtarSiteProfile'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'base_color': ('django.db.models.fields.CharField', [], {'default': "'rgba(0, 0, 0, 0)'", 'max_length': '200'}), + 'base_find_external_id': ('django.db.models.fields.TextField', [], {'default': "'{context_record__external_id}-{label}'"}), + 'container_external_id': ('django.db.models.fields.TextField', [], {'default': "'{responsible__external_id}-{index}'"}), + 'context_record': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'context_record_color': ('django.db.models.fields.CharField', [], {'default': "'rgba(210,200,0,0.2)'", 'max_length': '200'}), + 'context_record_external_id': ('django.db.models.fields.TextField', [], {'default': "'{parcel__external_id}-{label}'"}), + 'currency': ('django.db.models.fields.CharField', [], {'default': "u'\\u20ac'", 'max_length': "'5'"}), + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'file_external_id': ('django.db.models.fields.TextField', [], {'default': "'{year}-{numeric_reference}'"}), + 'files': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'files_color': ('django.db.models.fields.CharField', [], {'default': "'rgba(0, 32, 210, 0.1)'", 'max_length': '200'}), + 'find': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'find_color': ('django.db.models.fields.CharField', [], {'default': "'rgba(210,0,0,0.15)'", 'max_length': '200'}), + 'find_external_id': ('django.db.models.fields.TextField', [], {'default': "'{get_first_base_find__context_record__external_id}-{label}'"}), + 'find_index': ('django.db.models.fields.CharField', [], {'default': "'O'", 'max_length': '2'}), + 'homepage': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'label': ('django.db.models.fields.TextField', [], {}), + 'mapping': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'mapping_color': ('django.db.models.fields.CharField', [], {'default': "'rgba(72, 236, 0, 0.15)'", 'max_length': '200'}), + 'parcel_external_id': ('django.db.models.fields.TextField', [], {'default': "'{associated_file__external_id}{operation__code_patriarche}-{town__numero_insee}-{section}{parcel_number}'"}), + 'person_raw_name': ('django.db.models.fields.TextField', [], {'default': "'{name|upper} {surname}'"}), + 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50'}), + 'warehouse': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'warehouse_color': ('django.db.models.fields.CharField', [], {'default': "'rgba(10,20,200,0.15)'", 'max_length': '200'}), + 'warehouse_external_id': ('django.db.models.fields.TextField', [], {'default': "'{name|slug}'"}) + }, + 'ishtar_common.ishtaruser': { + 'Meta': {'object_name': 'IshtarUser', '_ormbases': ['auth.User']}, + 'advanced_shortcut_menu': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + '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.itemkey': { + 'Meta': {'object_name': 'ItemKey'}, + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'importer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.Import']", 'null': 'True', 'blank': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}) + }, + 'ishtar_common.operationtype': { + 'Meta': {'ordering': "['-preventive', 'order', 'label']", 'object_name': 'OperationType'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + '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'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '1'}), + 'preventive': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'txt_idx': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}) + }, + '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'}), + 'alt_address': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'alt_address_complement': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'alt_address_is_prefered': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'alt_country': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}), + 'alt_postal_code': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}), + 'alt_town': ('django.db.models.fields.CharField', [], {'max_length': '70', 'null': 'True', 'blank': 'True'}), + 'archived': ('django.db.models.fields.NullBooleanField', [], {'default': 'False', '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': '300', 'null': 'True', 'blank': 'True'}), + 'history_creator': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['auth.User']"}), + 'history_modifier': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['auth.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'imports': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'imported_ishtar_common_organization'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['ishtar_common.Import']"}), + 'merge_candidate': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'merge_candidate_rel_+'", 'null': 'True', 'to': "orm['ishtar_common.Organization']"}), + 'merge_exclusion': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'merge_exclusion_rel_+'", 'null': 'True', 'to': "orm['ishtar_common.Organization']"}), + 'merge_key': ('django.db.models.fields.TextField', [], {'null': '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': '500'}), + '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'}), + 'phone2': ('django.db.models.fields.CharField', [], {'max_length': '18', 'null': 'True', 'blank': 'True'}), + 'phone3': ('django.db.models.fields.CharField', [], {'max_length': '18', 'null': 'True', 'blank': 'True'}), + 'phone_desc': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True', 'blank': 'True'}), + 'phone_desc2': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True', 'blank': 'True'}), + 'phone_desc3': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True', 'blank': 'True'}), + 'postal_code': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}), + 'raw_phone': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'town': ('django.db.models.fields.CharField', [], {'max_length': '70', 'null': 'True', 'blank': 'True'}) + }, + 'ishtar_common.organizationtype': { + 'Meta': {'ordering': "('label',)", 'object_name': 'OrganizationType'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + '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': '100'}) + }, + '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'}), + 'alt_address': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'alt_address_complement': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'alt_address_is_prefered': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'alt_country': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}), + 'alt_postal_code': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}), + 'alt_town': ('django.db.models.fields.CharField', [], {'max_length': '70', 'null': 'True', 'blank': 'True'}), + 'archived': ('django.db.models.fields.NullBooleanField', [], {'default': 'False', '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']"}), + 'comment': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'contact_type': ('django.db.models.fields.CharField', [], {'max_length': '300', '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': '300', 'null': 'True', 'blank': 'True'}), + 'history_creator': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['auth.User']"}), + 'history_modifier': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['auth.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'imports': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'imported_ishtar_common_person'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['ishtar_common.Import']"}), + 'merge_candidate': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'merge_candidate_rel_+'", 'null': 'True', 'to': "orm['ishtar_common.Person']"}), + 'merge_exclusion': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'merge_exclusion_rel_+'", 'null': 'True', 'to': "orm['ishtar_common.Person']"}), + 'merge_key': ('django.db.models.fields.TextField', [], {'null': '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': '200', 'null': 'True', 'blank': 'True'}), + 'old_title': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), + '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'}), + 'phone2': ('django.db.models.fields.CharField', [], {'max_length': '18', 'null': 'True', 'blank': 'True'}), + 'phone3': ('django.db.models.fields.CharField', [], {'max_length': '18', 'null': 'True', 'blank': 'True'}), + 'phone_desc': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True', 'blank': 'True'}), + 'phone_desc2': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True', 'blank': 'True'}), + 'phone_desc3': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True', 'blank': 'True'}), + 'postal_code': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}), + 'raw_name': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True', 'blank': 'True'}), + 'raw_phone': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'salutation': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'surname': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), + 'title': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.TitleType']", 'null': 'True', 'blank': 'True'}), + 'town': ('django.db.models.fields.CharField', [], {'max_length': '70', 'null': 'True', 'blank': 'True'}) + }, + 'ishtar_common.persontype': { + 'Meta': {'ordering': "('label',)", 'object_name': 'PersonType'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + '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': '100'}) + }, + 'ishtar_common.regexp': { + 'Meta': {'object_name': 'Regexp'}, + 'description': ('django.db.models.fields.CharField', [], {'max_length': '500', 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'regexp': ('django.db.models.fields.CharField', [], {'max_length': '500'}) + }, + 'ishtar_common.sourcetype': { + 'Meta': {'ordering': "['label']", 'object_name': 'SourceType'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + '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': '100'}) + }, + 'ishtar_common.spatialreferencesystem': { + 'Meta': {'ordering': "('label',)", 'object_name': 'SpatialReferenceSystem'}, + 'auth_name': ('django.db.models.fields.CharField', [], {'default': "'EPSG'", 'max_length': '256'}), + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + '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'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '10'}), + 'srid': ('django.db.models.fields.IntegerField', [], {}), + 'txt_idx': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}) + }, + 'ishtar_common.state': { + 'Meta': {'ordering': "['number']", 'object_name': 'State'}, + '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.supporttype': { + 'Meta': {'object_name': 'SupportType'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + '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': '100'}) + }, + 'ishtar_common.targetkey': { + 'Meta': {'unique_together': "(('target', 'key', 'associated_user', 'associated_import'),)", 'object_name': 'TargetKey'}, + 'associated_import': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.Import']", 'null': 'True', 'blank': 'True'}), + 'associated_user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.IshtarUser']", 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_set': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'key': ('django.db.models.fields.TextField', [], {}), + 'target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'keys'", 'to': "orm['ishtar_common.ImportTarget']"}), + 'value': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}) + }, + 'ishtar_common.titletype': { + 'Meta': {'ordering': "('label',)", 'object_name': 'TitleType'}, + 'available': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + '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': '100'}) + }, + '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'}), + 'imports': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'imported_ishtar_common_town'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['ishtar_common.Import']"}), + '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']
\ No newline at end of file diff --git a/ishtar_common/models.py b/ishtar_common/models.py index 83127f2f0..0277ddefb 100644 --- a/ishtar_common/models.py +++ b/ishtar_common/models.py @@ -28,9 +28,11 @@ from PIL import Image from importlib import import_module import logging import os +from os.path import isfile, join import re from secretary import Renderer as SecretaryRenderer import shutil +from subprocess import Popen, PIPE import tempfile import time import unicodecsv @@ -3036,7 +3038,7 @@ post_delete.connect(post_save_cache, sender=Format) class Source(OwnPerms, ImageModel, models.Model): title = models.CharField(_(u"Title"), max_length=300) - external_id = models.CharField(_(u"External ID"), max_length=12, null=True, + external_id = models.TextField(_(u"External ID"), max_length=300, null=True, blank=True) source_type = models.ForeignKey(SourceType, verbose_name=_(u"Type")) support_type = models.ForeignKey(SupportType, verbose_name=_(u"Support"), @@ -3196,3 +3198,123 @@ class SpatialReferenceSystem(GeneralType): ordering = ('label',) post_save.connect(post_save_cache, sender=SpatialReferenceSystem) post_delete.connect(post_save_cache, sender=SpatialReferenceSystem) + + +class AdministrationScript(models.Model): + path = models.CharField(_(u"Filename"), max_length=30) + name = models.TextField(_(u"Name"), + null=True, blank=True) + + class Meta: + verbose_name = _(u"Administration script") + verbose_name_plural = _(u"Administration scripts") + ordering = ['name'] + + def __unicode__(self): + return unicode(self.name) + + +SCRIPT_STATE = (("S", _(u"Scheduled")), + ("P", _(u"In progress")), + ("FE", _(u"Finished with errors")), + ("F", _(u"Finished")), + ) + +SCRIPT_STATE_DCT = dict(SCRIPT_STATE) + + +class AdministrationTask(models.Model): + script = models.ForeignKey(AdministrationScript) + state = models.CharField(_(u"State"), max_length=2, choices=SCRIPT_STATE, + default='S') + creation_date = models.DateTimeField(default=datetime.datetime.now) + launch_date = models.DateTimeField(null=True, blank=True) + finished_date = models.DateTimeField(null=True, blank=True) + result = models.TextField(_(u"Result"), null=True, blank=True) + + class Meta: + verbose_name = _(u"Administration task") + verbose_name_plural = _(u"Administration tasks") + ordering = ['script'] + + def __unicode__(self): + state = _(u"Unknown") + if self.state in SCRIPT_STATE_DCT: + state = unicode(SCRIPT_STATE_DCT[self.state]) + return u"{} - {} - {}".format(self.script, self.creation_date, + state) + + def execute(self): + if self.state != 'S': + return + self.launch_date = datetime.datetime.now() + + script_dir = settings.ISHTAR_SCRIPT_DIR + + if not script_dir: + self.result = unicode( + _(u"ISHTAR_SCRIPT_DIR is not set in your " + u"local_settings. Contact your administrator.")) + self.state = 'FE' + self.finished_date = datetime.datetime.now() + self.save() + return + + if '..' in script_dir: + self.result = unicode( + _(u"Your ISHTAR_SCRIPT_DIR is containing " + u"dots \"..\". As it can refer to relative " + u"paths, it can be a security issue and this is " + u"not allowed. Only put a full path.")) + self.state = 'FE' + self.finished_date = datetime.datetime.now() + self.save() + return + + if not os.path.isdir(script_dir): + self.result = unicode( + _(u"Your ISHTAR_SCRIPT_DIR: \"{}\" is not a valid directory.") + ).format(script_dir) + self.state = 'FE' + self.finished_date = datetime.datetime.now() + self.save() + return + + script_name = None + # only script inside the script directory can be executed + for name in os.listdir(script_dir): + if name == self.script.path: + if isfile(join(script_dir, name)): + script_name = join(script_dir, name) + break + if not script_name: + self.result = unicode( + _(u"Script \"{}\" is not available in your script directory. " + u"Check your configuration.") + ).format(self.script.path) + self.state = 'FE' + self.finished_date = datetime.datetime.now() + self.save() + return + self.state = 'P' + self.save() + + self.finished_date = datetime.datetime.now() + try: + session = Popen([script_name], stdout=PIPE, stderr=PIPE) + stdout, stderr = session.communicate() + except OSError as e: + self.state = 'FE' + self.result = u"Error executing \"{}\" script: {}".format( + self.script.path, e) + self.save() + return + + self.finished_date = datetime.datetime.now() + if stderr: + self.state = 'FE' + self.result = u"Error: {}".format(stderr) + else: + self.state = 'F' + self.result = u"{}".format(stdout) + self.save() diff --git a/ishtar_common/templates/blocks/form_snippet.html b/ishtar_common/templates/blocks/form_snippet.html index 2f841e078..5ee88e25f 100644 --- a/ishtar_common/templates/blocks/form_snippet.html +++ b/ishtar_common/templates/blocks/form_snippet.html @@ -10,4 +10,7 @@ </tr> <tr class="help_text" id="{{field.auto_id}}_help"> <td colspan="3"><div>{{field.help_text}}</div></td> - {%endif%}</tr>{% else %}{{field}}{% endif %}{% endfor %} + {%endif%}</tr>{% else %}{{field}}{% if field.errors %} + <tr class='errors'> + <td colspan='3'>{{field.name}} - {{ field.errors }}</td> + </tr>{% endif %}{{field|safe}}{% endif %}{% endfor %} diff --git a/ishtar_common/tests.py b/ishtar_common/tests.py index 63b46c40c..d89c8546c 100644 --- a/ishtar_common/tests.py +++ b/ishtar_common/tests.py @@ -192,9 +192,11 @@ class WizardTest(object): self.wizard_name): [current_step], } + + # reconstruct a POST request if current_step in form_data: d = form_data[current_step] - if type(d) in (list, tuple): # formset + if type(d) in (list, tuple): # is a formset for d_idx, item in enumerate(d): for k in item: data['{}-{}-{}'.format( @@ -209,16 +211,21 @@ class WizardTest(object): response = self.client.post( url, data, follow=not next_form_is_checked) except ValidationError as e: - # on ManagementForm data is missing or has been tampered - # error verify the wizard_name or step name - raise ValidationError(u"Errors: {} on {}.".format( - u" - ".join(e.messages), current_step)) + msg = u"Errors: {} on {}. On \"ManagementForm data is " \ + u"missing or...\" error verify the wizard_name or " \ + u"step name".format(u" - ".join(e.messages), + current_step) + raise ValidationError(msg) self.check_response(response, current_step) if next_form_is_checked: next_form = self.steps[idx + 1][0] self.assertRedirects( response, - '/{}/{}'.format(self.url_name, next_form)) + '/{}/{}'.format(self.url_name, next_form), + msg_prefix="Redirection to {} has failed - " + "Error on previous form ({})?".format( + next_form, current_step) + ) if idx == len(self.steps) - 1: # last form self.assertRedirects( |