diff options
author | Étienne Loks <etienne.loks@iggdrasil.net> | 2025-10-15 19:03:22 +0200 |
---|---|---|
committer | Étienne Loks <etienne.loks@iggdrasil.net> | 2025-10-15 19:32:59 +0200 |
commit | 31ae6562099cca5e692fdcdccf0852433d295a3a (patch) | |
tree | 365de723a1b9430e1d6f44618c52f2dd4a1abe48 /ishtar_common | |
parent | f5077bcd3cea76f48a2d635385e4b85a16bf6000 (diff) | |
download | Ishtar-31ae6562099cca5e692fdcdccf0852433d295a3a.tar.bz2 Ishtar-31ae6562099cca5e692fdcdccf0852433d295a3a.zip |
♻️ django 3.2 deprecation: url -> re_path ; ugettext_lazy -> gettext_lazy
Diffstat (limited to 'ishtar_common')
27 files changed, 204 insertions, 202 deletions
diff --git a/ishtar_common/__init__.py b/ishtar_common/__init__.py index fd8fb9357..d398224aa 100644 --- a/ishtar_common/__init__.py +++ b/ishtar_common/__init__.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- # Copyright (C) 2014-2025 Étienne Loks <etienne.loks at iggdrasil dot net> -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ # overload of translation of registration module _("username") diff --git a/ishtar_common/admin.py b/ishtar_common/admin.py index dbce4670f..fd1b4e5c3 100644 --- a/ishtar_common/admin.py +++ b/ishtar_common/admin.py @@ -34,7 +34,6 @@ from rest_framework.authtoken.models import Token from axes import models as axes_models from axes.admin import AccessAttemptAdmin, AccessLogAdmin from django.conf import settings -from django.conf.urls import url from django.contrib import admin, messages from django.contrib.admin.views.main import ChangeList from django.contrib.auth.admin import GroupAdmin, UserAdmin @@ -61,11 +60,11 @@ from django.db.models.fields.related import ForeignKey from django.forms import BaseInlineFormSet from django.http import HttpResponseRedirect, HttpResponse, Http404 from django.shortcuts import render -from django.urls import reverse +from django.urls import re_path, reverse from django.utils.decorators import method_decorator from django.utils.text import slugify from django.utils.safestring import mark_safe -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from django.views.decorators.csrf import csrf_protect from django import forms @@ -1120,7 +1119,7 @@ class ImportActionAdmin(admin.ModelAdmin): def get_urls(self): urls = super(ImportActionAdmin, self).get_urls() my_urls = [ - url(r"^import-from-csv/$", self.import_generic), + re_path(r"^import-from-csv/$", self.import_generic), ] return my_urls + urls @@ -1278,7 +1277,7 @@ class ImportGEOJSONActionAdmin(object): def get_urls(self): urls = super(ImportGEOJSONActionAdmin, self).get_urls() my_urls = [ - url(r"^import-from-geojson/$", self.import_geojson), + re_path(r"^import-from-geojson/$", self.import_geojson), ] return my_urls + urls @@ -1504,7 +1503,7 @@ class ImportJSONActionAdmin(admin.ModelAdmin): def get_urls(self): urls = super(ImportJSONActionAdmin, self).get_urls() my_urls = [ - url(r"^import-from-json/$", self.import_json), + re_path(r"^import-from-json/$", self.import_json), ] return my_urls + urls @@ -1773,7 +1772,7 @@ class CreateDepartmentActionAdmin(GeneralTypeAdmin): def get_urls(self): urls = super(CreateDepartmentActionAdmin, self).get_urls() my_urls = [ - url(r"^create-department/$", self.create_area), + re_path(r"^create-department/$", self.create_area), ] return my_urls + urls diff --git a/ishtar_common/apps.py b/ishtar_common/apps.py index 2a726dd4c..0c37c6370 100644 --- a/ishtar_common/apps.py +++ b/ishtar_common/apps.py @@ -4,7 +4,7 @@ from django.http import Http404 from django.template.response import TemplateResponse from django.urls import NoReverseMatch, reverse from django.utils.text import capfirst -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ class IshtarAdminSite(AdminSite): diff --git a/ishtar_common/context_processors.py b/ishtar_common/context_processors.py index ce379a4cd..5442b08fe 100644 --- a/ishtar_common/context_processors.py +++ b/ishtar_common/context_processors.py @@ -25,7 +25,7 @@ from django.conf import settings from django.core.cache import cache from django.contrib.sites.models import Site from django.urls import reverse -from django.utils.translation import ugettext_lazy as _, get_language +from django.utils.translation import gettext_lazy as _, get_language from ishtar_common.version import __version__ from ishtar_common.models import get_current_profile diff --git a/ishtar_common/data_importer.py b/ishtar_common/data_importer.py index 9dbe0b3e9..253cd593e 100644 --- a/ishtar_common/data_importer.py +++ b/ishtar_common/data_importer.py @@ -36,7 +36,7 @@ from django.core.files import File from django.db import IntegrityError, DatabaseError, transaction from django.db.models import Q from django.template.defaultfilters import slugify -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from ishtar_common.utils import ( get_all_field_names, diff --git a/ishtar_common/forms.py b/ishtar_common/forms.py index f16a3eeb9..ac0c638e1 100644 --- a/ishtar_common/forms.py +++ b/ishtar_common/forms.py @@ -39,7 +39,7 @@ from django.utils import formats, translation from django.utils.functional import lazy from django.utils.safestring import mark_safe from django.utils.text import slugify -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from bootstrap_datepicker.widgets import DatePicker, DATE_FORMAT from ishtar_common import models diff --git a/ishtar_common/forms_common.py b/ishtar_common/forms_common.py index 56942fbe0..a77b94618 100644 --- a/ishtar_common/forms_common.py +++ b/ishtar_common/forms_common.py @@ -49,7 +49,7 @@ from django.forms.models import BaseModelFormSet, BaseFormSet from django.shortcuts import reverse from django.utils.text import slugify from django.utils.safestring import mark_safe -from django.utils.translation import ugettext_lazy as _, pgettext +from django.utils.translation import gettext_lazy as _, pgettext from . import models, models_rest from .models_imports import FORMATER_WIDGETS_DCT diff --git a/ishtar_common/ishtar_menu.py b/ishtar_common/ishtar_menu.py index 8eb9c5932..0235db8d1 100644 --- a/ishtar_common/ishtar_menu.py +++ b/ishtar_common/ishtar_menu.py @@ -17,7 +17,7 @@ # See the file COPYING for details. -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from ishtar_common.menu_base import SectionItem, MenuItem diff --git a/ishtar_common/management/commands/migrate_to_geo_v4.py b/ishtar_common/management/commands/migrate_to_geo_v4.py index 343fc85f3..d432e33b6 100644 --- a/ishtar_common/management/commands/migrate_to_geo_v4.py +++ b/ishtar_common/management/commands/migrate_to_geo_v4.py @@ -12,7 +12,7 @@ from django.conf import settings from django.contrib.contenttypes.models import ContentType from django.core.management.base import BaseCommand -from ishtar_common.utils import ugettext_lazy as _, get_log_time, get_percent, get_eta +from ishtar_common.utils import gettext_lazy as _, get_log_time, get_percent, get_eta from ishtar_common import models_common, models from archaeological_operations.models import Operation, ArchaeologicalSite diff --git a/ishtar_common/models.py b/ishtar_common/models.py index da827f99b..4ae11a777 100644 --- a/ishtar_common/models.py +++ b/ishtar_common/models.py @@ -82,8 +82,8 @@ from django.utils.functional import lazy from django.utils.safestring import mark_safe from ishtar_common.data_importer import ImporterError, post_importer_action from ishtar_common.utils import ( - ugettext_lazy as _, - ugettext, + gettext_lazy as _, + gettext, pgettext_lazy, format_date, get_generated_id, @@ -5291,9 +5291,9 @@ class Document( verbose_name_plural = _("Documents") ordering = ("title",) permissions = ( - ("view_own_document", ugettext("Can view own Document")), - ("change_own_document", ugettext("Can change own Document")), - ("delete_own_document", ugettext("Can delete own Document")), + ("view_own_document", gettext("Can view own Document")), + ("change_own_document", gettext("Can change own Document")), + ("delete_own_document", gettext("Can delete own Document")), ) indexes = [ GinIndex(fields=["data"]), diff --git a/ishtar_common/models_common.py b/ishtar_common/models_common.py index daf2d9885..ea7303089 100644 --- a/ishtar_common/models_common.py +++ b/ishtar_common/models_common.py @@ -47,7 +47,7 @@ from django.utils.safestring import SafeText, mark_safe from django.utils.translation import activate, deactivate from ishtar_common.utils import ( BColors, - ugettext_lazy as _, + gettext_lazy as _, pgettext_lazy, get_image_path, get_columns_from_class, diff --git a/ishtar_common/models_imports.py b/ishtar_common/models_imports.py index a935c0e21..3ebbb8068 100644 --- a/ishtar_common/models_imports.py +++ b/ishtar_common/models_imports.py @@ -53,7 +53,7 @@ from django.db.models.base import ModelBase from django.db.models.signals import pre_delete from django.template.defaultfilters import slugify from django.utils.functional import cached_property -from django.utils.translation import ugettext_lazy as _, pgettext_lazy +from django.utils.translation import gettext_lazy as _, pgettext_lazy UnoCalc = None ITALIC = None diff --git a/ishtar_common/models_rest.py b/ishtar_common/models_rest.py index 8f6f8d40c..9ed9abd3e 100644 --- a/ishtar_common/models_rest.py +++ b/ishtar_common/models_rest.py @@ -14,7 +14,7 @@ from django.apps import apps from django.template import loader from ishtar_common.models_common import BaseSheetFilter -from ishtar_common.utils import ugettext_lazy as _ +from ishtar_common.utils import gettext_lazy as _ UnoCalc = None ITALIC = None diff --git a/ishtar_common/tasks.py b/ishtar_common/tasks.py index ba5a346e1..55c704ab1 100644 --- a/ishtar_common/tasks.py +++ b/ishtar_common/tasks.py @@ -25,7 +25,7 @@ import sys from django.conf import settings from django.core.files import File from django.db.models import Q -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from ishtar_common.models_common import Town, Department from ishtar_common.utils import task diff --git a/ishtar_common/templatetags/date_formating.py b/ishtar_common/templatetags/date_formating.py index 8d81fc578..f0504318b 100644 --- a/ishtar_common/templatetags/date_formating.py +++ b/ishtar_common/templatetags/date_formating.py @@ -4,7 +4,7 @@ from datetime import datetime from django.template import Library -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ register = Library() diff --git a/ishtar_common/templatetags/table_form.py b/ishtar_common/templatetags/table_form.py index 01bb5679c..f1c3f688f 100644 --- a/ishtar_common/templatetags/table_form.py +++ b/ishtar_common/templatetags/table_form.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- from django.template import Library -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ register = Library() diff --git a/ishtar_common/templatetags/window_field.py b/ishtar_common/templatetags/window_field.py index 576a7d3cc..721f39ef5 100644 --- a/ishtar_common/templatetags/window_field.py +++ b/ishtar_common/templatetags/window_field.py @@ -2,7 +2,7 @@ import os from django import template from django.template import loader -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from django.utils.safestring import mark_safe from ishtar_common.models import HistoryModel, Town diff --git a/ishtar_common/templatetags/window_tables.py b/ishtar_common/templatetags/window_tables.py index 5685fbc93..bcd3a7b8c 100644 --- a/ishtar_common/templatetags/window_tables.py +++ b/ishtar_common/templatetags/window_tables.py @@ -7,7 +7,7 @@ from django.template.defaultfilters import slugify from django.template.loader import get_template from django.urls import resolve from django.utils.safestring import mark_safe -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from ishtar_common.forms import reverse_lazy from ishtar_common.widgets import DataTable diff --git a/ishtar_common/tests.py b/ishtar_common/tests.py index 18e1d9c38..bbe5db892 100644 --- a/ishtar_common/tests.py +++ b/ishtar_common/tests.py @@ -56,7 +56,7 @@ from django.template.defaultfilters import slugify from django.test import TestCase as BaseTestCase from django.test.client import Client from django.test.runner import DiscoverRunner -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from django.urls import reverse from ishtar_common import models, models_common, forms_common diff --git a/ishtar_common/urls.py b/ishtar_common/urls.py index b9eb88c2b..a66947183 100644 --- a/ishtar_common/urls.py +++ b/ishtar_common/urls.py @@ -18,9 +18,9 @@ # See the file COPYING for details. from django.conf import settings -from django.conf.urls import include, url +from django.conf.urls import include from django.conf.urls.static import static -from django.urls import path +from django.urls import path, re_path from django.views.generic import TemplateView from .menus import Menu @@ -32,37 +32,37 @@ from ishtar_common.utils import check_permissions, get_urls_for_model # forms urlpatterns = [ - url(r"^status/$", views.status, name="status"), - url(r"^raise-error/$", views.raise_error, name="raise-error"), - url(r"^raise-task-error/$", views.raise_task_error, name="raise-task-error"), - url(r"^ty/(?P<url_id>[a-zA-Z0-9]+)$", views.tiny_redirect, name="tiny-redirect"), - url( + re_path(r"^status/$", views.status, name="status"), + re_path(r"^raise-error/$", views.raise_error, name="raise-error"), + re_path(r"^raise-task-error/$", views.raise_task_error, name="raise-task-error"), + re_path(r"^ty/(?P<url_id>[a-zA-Z0-9]+)$", views.tiny_redirect, name="tiny-redirect"), + re_path( r"^robots\.txt$", TemplateView.as_view(template_name="robots.txt", content_type="text/plain"), ), # internationalization - url(r"^i18n/", include("django.conf.urls.i18n")), - url(r"^js/settings.js", views.settings_js, name="settings-js"), + re_path(r"^i18n/", include("django.conf.urls.i18n")), + re_path(r"^js/settings.js", views.settings_js, name="settings-js"), # General - url(r"shortcut_menu/", views.shortcut_menu, name="shortcut-menu"), - url(r"news-feed/", views.display_news_feed, name="news-feed"), - url( + re_path(r"shortcut_menu/", views.shortcut_menu, name="shortcut-menu"), + re_path(r"news-feed/", views.display_news_feed, name="news-feed"), + re_path( r"display/(?P<item_type>\w+)/(?P<pk>\d+)/", views.DisplayItemView.as_view(), name="display-item", ), - url(r"qrcode/search/", views.QRCodeForSearchView.as_view(), name="search-qrcode"), - url( + re_path(r"qrcode/search/", views.QRCodeForSearchView.as_view(), name="search-qrcode"), + re_path( r"qrcode/(?P<app>[-a-z]+)/(?P<model_name>[-a-z]+)/(?P<pk>\d+)/", views.QRCodeView.as_view(), name="qrcode-item", ), - url( + re_path( r"^generate-labels/(?P<template_slug>[-a-z0-9]+)/", views.GenerateLabelView.as_view(), name="generate-labels", ), - url( + re_path( r"^generate-document/(?P<template_slug>[-a-z0-9]+)/(" r"?P<item_pk>\d+)/", views.GenerateView.as_view(), name="generate-document", @@ -72,54 +72,54 @@ urlpatterns = [ views.ExportMediaView.as_view(), name="export-media" ), - url( + re_path( r"person_search/(?P<step>.+)?$", check_permissions( ["ishtar_common.view_person", "ishtar_common.view_own_person"] )(views.person_search_wizard), name="person_search", ), - url( + re_path( r"person_creation/(?P<step>.+)?$", check_permissions(["ishtar_common.add_person"])(views.person_creation_wizard), name="person_creation", ), - url( + re_path( r"person_modification/(?P<step>.+)?$", check_permissions( ["ishtar_common.change_person", "ishtar_common.change_own_person"] )(views.person_modification_wizard), name="person_modification", ), - url(r"person_modify/(?P<pk>.+)/$", views.person_modify, name="person_modify"), - url( + re_path(r"person_modify/(?P<pk>.+)/$", views.person_modify, name="person_modify"), + re_path( r"person_deletion/(?P<step>.+)?$", check_permissions( ["ishtar_common.delete_person", "ishtar_common.delete_own_person"] )(views.person_deletion_wizard), name="person_deletion", ), - url(r"person_delete/(?P<pk>.+)/$", views.person_delete, name="person_delete"), - url( + re_path(r"person_delete/(?P<pk>.+)/$", views.person_delete, name="person_delete"), + re_path( r"^person-edit/$", check_permissions(["ishtar_common.add_person"])(views.PersonCreate.as_view()), name="person_create", ), - url( + re_path( r"^person-edit/(?P<pk>\d+)$", check_permissions( ["ishtar_common.change_person", "ishtar_common.change_own_person"] )(views.PersonEdit.as_view()), name="person_edit", ), - url( + re_path( r"^person-qa-bulk-update/(?P<pks>[0-9-]+)?/$", check_permissions( ["ishtar_common.change_person", "ishtar_common.change_own_person"] )(views.QAPersonForm.as_view()), name="person-qa-bulk-update", ), - url( + re_path( r"^person-qa-bulk-update/(?P<pks>[0-9-]+)?/confirm/$", check_permissions( ["ishtar_common.change_person", "ishtar_common.change_own_person"] @@ -127,52 +127,52 @@ urlpatterns = [ name="person-qa-bulk-update-confirm", kwargs={"confirm": True}, ), - url( + re_path( r"organization_search/(?P<step>.+)?$", check_permissions( ["ishtar_common.view_organization", "ishtar_common.view_own_organization"] )(views.organization_search_wizard), name="organization_search", ), - url( + re_path( r"organization_creation/(?P<step>.+)?$", check_permissions( ["ishtar_common.add_organization"] )(views.organization_creation_wizard), name="organization_creation", ), - url( + re_path( r"organization_modification/(?P<step>.+)?$", check_permissions( ["ishtar_common.change_organization", "ishtar_common.change_own_organization"] )(views.organization_modification_wizard), name="organization_modification", ), - url( + re_path( r"organization_modify/(?P<pk>.+)/$", views.organization_modify, name="organization_modify", ), - url( + re_path( r"organization_deletion/(?P<step>.+)?$", check_permissions( ["ishtar_common.delete_organization", "ishtar_common.delete_own_organization"] )(views.organization_deletion_wizard), name="organization_deletion", ), - url( + re_path( r"organization_delete/(?P<pk>.+)/$", views.organization_delete, name="delete-organization", ), - url( + re_path( r"organization-edit/$", check_permissions( ["ishtar_common.add_organization"] )(views.OrganizationCreate.as_view()), name="organization_create", ), - url( + re_path( r"organization-edit/(?P<pk>\d+)$", check_permissions( ["ishtar_common.change_organization", @@ -180,28 +180,28 @@ urlpatterns = [ )(views.OrganizationEdit.as_view()), name="organization_edit", ), - url( + re_path( r"organization-person-edit/$", check_permissions( ["ishtar_common.add_organization"] )(views.OrganizationPersonCreate.as_view()), name="organization_person_create", ), - url( + re_path( r"organization-person-edit/(?P<pk>\d+)$", check_permissions( ["ishtar_common.change_organization", "ishtar_common.change_own_organization"] )(views.OrganizationPersonEdit.as_view()), name="organization_person_edit", ), - url( + re_path( r"^organization-qa-bulk-update/(?P<pks>[0-9-]+)?/$", check_permissions( ["ishtar_common.change_organization", "ishtar_common.change_own_organization"] )(views.QAOrganizationForm.as_view()), name="organization-qa-bulk-update", ), - url( + re_path( r"^organization-qa-bulk-update/(?P<pks>[0-9-]+)?/confirm/$", check_permissions( ["ishtar_common.change_organization", "ishtar_common.change_own_organization"] @@ -209,55 +209,55 @@ urlpatterns = [ name="organization-qa-bulk-update-confirm", kwargs={"confirm": True}, ), - url(r"get-ishtaruser/(?P<type>.+)?$", views.get_ishtaruser, name="get-ishtaruser"), - url( + re_path(r"get-ishtaruser/(?P<type>.+)?$", views.get_ishtaruser, name="get-ishtaruser"), + re_path( r"account_management/(?P<step>.+)?$", check_permissions( ["ishtar_common.add_ishtaruser"] )(views.account_management_wizard), name="account_management", ), - url( + re_path( r"account_manage/(?P<pk>\d+)$", views.account_manage, name="account-manage", ), - url( + re_path( r"account_deletion/(?P<step>.+)?$", check_permissions( ["ishtar_common.add_ishtaruser"] )(views.account_deletion_wizard), name="account_deletion", ), - url( + re_path( r"^import-new/$", check_permissions( ["ishtar_common.add_import", "ishtar_common.add_own_import"] )(views.NewImportView.as_view()), name="new_import", ), - url( + re_path( r"^import-edit/(?P<pk>[0-9]+)/$", check_permissions( ["ishtar_common.change_import", "ishtar_common.change_own_import"] )(views.EditImportView.as_view()), name="edit_import", ), - url( + re_path( r"^import-new-gis/$", check_permissions( ["ishtar_common.add_import", "ishtar_common.add_own_import"] )(views.NewImportGISView.as_view()), name="new_import_gis", ), - url( + re_path( r"^import-new-group/$", check_permissions( ["ishtar_common.add_import", "ishtar_common.add_own_import"] )(views.NewImportGroupView.as_view()), name="new_import_group", ), - url( + re_path( r"^import-list/$", check_permissions( ["ishtar_common.view_import", "ishtar_common.view_own_import", @@ -265,7 +265,7 @@ urlpatterns = [ )(views.ImportListView.as_view()), name="current_imports", ), - url( + re_path( r"^import-list-table/$", check_permissions( ["ishtar_common.view_import", "ishtar_common.view_own_import", @@ -273,7 +273,7 @@ urlpatterns = [ )(views.ImportListTableView.as_view()), name="current_imports_table", ), - url( + re_path( r"^import-get-status/$", check_permissions( ["ishtar_common.view_import", "ishtar_common.view_own_import", @@ -281,7 +281,7 @@ urlpatterns = [ )(views.import_get_status), name="import_get_status", ), - url( + re_path( r"^import-list-old/$", check_permissions( ["ishtar_common.view_import", "ishtar_common.view_own_import", @@ -289,78 +289,78 @@ urlpatterns = [ )(views.ImportOldListView.as_view()), name="old_imports", ), - url( + re_path( r"^import-delete/(?P<pk>[0-9]+)/$", check_permissions( ["ishtar_common.delete_import", "ishtar_common.delete_own_import"] )(views.ImportDeleteView.as_view()), name="import_delete", ), - url( + re_path( r"^import-group-delete/(?P<pk>[0-9]+)/$", check_permissions( ["ishtar_common.delete_import", "ishtar_common.delete_own_import"] )(views.ImportGroupDeleteView.as_view()), name="import_group_delete", ), - url( + re_path( r"^import-link-unmatched/(?P<pk>[0-9]+)/$", check_permissions( ["ishtar_common.change_import", "ishtar_common.change_own_import"] )(views.ImportMatchView.as_view()), name="import_link_unmatched", ), - url( + re_path( r"^import-csv-view/(?P<target>source|result|match|error)/(?P<group>group\-)?(?P<pk>[0-9]+)/$", check_permissions( ["ishtar_common.view_import", "ishtar_common.view_own_import"] )(views.ImportCSVView.as_view()), name="import_display_csv", ), - url( + re_path( r"^import-step-by-step/all/(?P<pk>[0-9]+)/(?P<line_number>[0-9]+)/$", views.ImportStepByStepView.as_view(), name="import_step_by_step_all", kwargs={"all_pages": True}, ), - url( + re_path( r"^import-step-by-step/(?P<pk>[0-9]+)/(?P<line_number>[0-9]+)/$", views.ImportStepByStepView.as_view(), name="import_step_by_step", ), - url( + re_path( r"^import-pre-form/(?P<import_id>[0-9]+)/$", check_permissions( ["ishtar_common.change_import", "ishtar_common.change_own_import"] )(views.ImportPreFormView.as_view()), name="import_pre_import_form", ), - url( + re_path( r"^import-ignore-line/(?P<line_id>[0-9]+)/$", check_permissions( ["ishtar_common.change_import", "ishtar_common.change_own_import"] )(views.line_error), name="import_ignore_line", ), - url(r"^profile(?:/(?P<pk>[0-9]+))?/$", views.ProfileEdit.as_view(), name="profile"), - url( + re_path(r"^profile(?:/(?P<pk>[0-9]+))?/$", views.ProfileEdit.as_view(), name="profile"), + re_path( r"^save-search/(?P<app_label>[a-z-]+)/(?P<model>[a-z-]+)/$", views.SearchQueryEdit.as_view(), name="save-search-query", ), - url( + re_path( r"^bookmarks/(?P<app_label>[a-z-]+)/(?P<model>[a-z-]+)/$", views.BookmarkList.as_view(), name="bookmark-list", ), - url(r"^bookmark/(?P<pk>[0-9]+)/$", views.get_bookmark, name="bookmark"), - url( + re_path(r"^bookmark/(?P<pk>[0-9]+)/$", views.get_bookmark, name="bookmark"), + re_path( r"^bookmark/delete/(?P<pk>[0-9]+)/$", views.SearchQueryDelete.as_view(), name="bookmark-delete", ), - url(r"^alerts/$", views.AlertList.as_view(), name="alert-list"), - url( + re_path(r"^alerts/$", views.AlertList.as_view(), name="alert-list"), + re_path( r"^success(?:/(?P<context>[a-z-]+)(?:/(?P<arg>[0-9a-z-|]+))?)?/$", views.SuccessView.as_view(), name="success", @@ -382,77 +382,77 @@ actions = r"|".join(actions) # other views urlpatterns += [ # General - url( + re_path( r"update-current-item/$", views.update_current_item, name="update-current-item" ), - url( + re_path( r"pin/(?P<item_type>[a-z-]+)/(?P<pk>\d+)/$", views.update_current_item, name="pin", ), - url(r"pin-search/(?P<item_type>[a-z-]+)/$", views.pin_search, name="pin-search"), - url(r"unpin/(?P<item_type>[a-z-]+)/$", views.unpin, name="unpin"), - url( + re_path(r"pin-search/(?P<item_type>[a-z-]+)/$", views.pin_search, name="pin-search"), + re_path(r"unpin/(?P<item_type>[a-z-]+)/$", views.unpin, name="unpin"), + re_path( r"get-by-importer/(?P<slug>[\w-]+)/(?P<type>[a-z-]+)?$", views.get_by_importer, name="get-by-importer", ), - url( + re_path( r"new-person/(?:(?P<parent_name>[^/]+)/)?(?:(?P<limits>[^/]+)/)?$", views.new_person, name="new-person", ), - url( + re_path( r"modify-person/(?:(?P<parent_name>[^/]+)/)?(?P<pk>[\d+]+)/$", views.modify_person, name="modify-person", ), - url(r"detail-person/(?P<pk>[\d+]+)/$", views.detail_person, name="detail-person"), - url( + re_path(r"detail-person/(?P<pk>[\d+]+)/$", views.detail_person, name="detail-person"), + re_path( r"modify-organization/(?:(?P<parent_name>[^/]+)/)?(?P<pk>[\d+]+)/$", views.modify_organization, name="modify-organization", ), - url( + re_path( r"detail-organization/(?P<pk>[\d+]+)/$", views.detail_organization, name="detail-organization", ), - url( + re_path( r"new-person-noorga/" r"(?:(?P<parent_name>[^/]+)/)?(?:(?P<limits>[^/]+)/)?$", views.new_person_noorga, name="new-person-noorga", ), - url(r"autocomplete-area/$", views.autocomplete_area, name="autocomplete-area"), - url(r"autocomplete-user/$", views.autocomplete_user, name="autocomplete-user"), - url( + re_path(r"autocomplete-area/$", views.autocomplete_area, name="autocomplete-area"), + re_path(r"autocomplete-user/$", views.autocomplete_user, name="autocomplete-user"), + re_path( r"autocomplete-ishtaruser/$", views.autocomplete_ishtaruser, name="autocomplete-ishtaruser", ), - url( + re_path( r"autocomplete-person(?:/([0-9_]+))?(?:/([0-9_]*))?/(user)?$", views.autocomplete_person, name="autocomplete-person", ), - url( + re_path( r"autocomplete-person-permissive(?:/([0-9_]+))?(?:/([0-9_]*))?" r"/(user)?$", views.autocomplete_person_permissive, name="autocomplete-person-permissive", ), - url(r"get-person/(?P<type>.+)?$", views.get_person, name="get-person"), - url( + re_path(r"get-person/(?P<type>.+)?$", views.get_person, name="get-person"), + re_path( r"get-person-full/(?P<type>.+)?$", views.get_person, name="get-person-full", kwargs={"full": True}, ), - url( + re_path( r"get-person-for-account/(?P<type>.+)?$", views.get_person_for_account, name="get-person-for-account", ), - url( + re_path( r"show-person(?:/(?P<pk>.+))?/(?P<type>.+)?$", views.show_person, name="show-person", @@ -467,17 +467,17 @@ urlpatterns += [ check_permissions(["ishtaradmin"])(views.show_ishtaruser), name="show-ishtaruser", ), - url( + re_path( r"show-biographicalnote(?:/(?P<pk>.+))?/(?P<type>.+)?$", views.show_biographical_note, name="show-biographicalnote", ), - url( + re_path( r"new-biographicalnote/(?:(?P<parent_name>[^/]+)/)?(?:(?P<limits>[^/]+)/)?$", views.new_biographical_note, name="new-biographicalnote", ), - url( + re_path( r"^biographicalnote-qa-edit/(?P<pks>[0-9-]+)?/$", check_permissions( ["ishtar_common.change_biographicalnote", @@ -485,129 +485,129 @@ urlpatterns += [ )(views.QABiographicalNoteForm.as_view()), name="biographicalnote-qa-edit", ), - url( + re_path( r"department-by-state/(?P<state_id>.+)?$", views.department_by_state, name="department-by-state", ), - url( + re_path( r"show-area(?:/(?P<pk>.+))?/(?P<type>.+)?$", views.show_area, name="show-area", ), - url( + re_path( r"show-town(?:/(?P<pk>.+))?/(?P<type>.+)?$", views.show_town, name="show-town", ), - url(r"autocomplete-town/?$", views.autocomplete_town, name="autocomplete-town"), - url( + re_path(r"autocomplete-town/?$", views.autocomplete_town, name="autocomplete-town"), + re_path( r"autocomplete-advanced-town/(?P<department_id>[0-9]+[ABab]?)?$", views.autocomplete_advanced_town, name="autocomplete-advanced-town", ), - url( + re_path( r"autocomplete-department/?$", views.autocomplete_department, name="autocomplete-department", ), - url( + re_path( r"new-author/(?:(?P<parent_name>[^/]+)/)?(?:(?P<limits>[^/]+)/)?$", views.new_author, name="new-author", ), - url( + re_path( r"autocomplete-author/$", views.autocomplete_author, name="autocomplete-author" ), - url( + re_path( r"new-organization/(?:(?P<parent_name>[^/]+)/)?" r"(?:(?P<limits>[^/]+)/)?$", views.new_organization, name="new-organization", ), - url( + re_path( r"get-organization/(?P<type>.+)?$", views.get_organization, name="get-organization", ), - url( + re_path( r"get-organization-full/(?P<type>.+)?$", views.get_organization, name="get-organization-full", kwargs={"full": True}, ), - url( + re_path( r"show-organization(?:/(?P<pk>.+))?/(?P<type>.+)?$", views.show_organization, name="show-organization", ), - url( + re_path( r"show-import(?:/(?P<pk>\d+))?/(?P<type>odt|pdf)?$", views.show_import, name="show-import", ), - url(r"autocomplete-import/$", views.autocomplete_import, name="autocomplete-import"), - url( + re_path(r"autocomplete-import/$", views.autocomplete_import, name="autocomplete-import"), + re_path( r"show-importgroup(?:/(?P<pk>\d+))?/(?P<type>odt|pdf)?$", views.show_import_group, name="show-importgroup", ), - url( + re_path( r"autocomplete-organization/([0-9_]+)?$", views.autocomplete_organization, name="autocomplete-organization", ), - url( + re_path( r"autocomplete-biographical-note/$", views.autocomplete_biographical_note, name="autocomplete-biographicalnote" ), - url(r"changelog/(?:(?P<page>\d+)/)?", views.ChangelogView.as_view(), name="changelog"), - url(r"person-merge/(?:(?P<page>\d+)/)?$", views.person_merge, name="person_merge"), - url( + re_path(r"changelog/(?:(?P<page>\d+)/)?", views.ChangelogView.as_view(), name="changelog"), + re_path(r"person-merge/(?:(?P<page>\d+)/)?$", views.person_merge, name="person_merge"), + re_path( r"person-manual-merge/$", views.PersonManualMerge.as_view(), name="person_manual_merge", ), - url( + re_path( r"person-manual-merge-items/(?P<pks>[0-9_]+?)/$", views.PersonManualMergeItems.as_view(), name="person_manual_merge_items", ), - url( + re_path( r"organization-merge/(?:(?P<page>\d+)/)?$", views.organization_merge, name="organization_merge", ), - url( + re_path( r"orga-manual-merge/$", views.OrgaManualMerge.as_view(), name="orga_manual_merge", ), - url( + re_path( r"orga-manual-merge-items/(?P<pks>[0-9_]+?)/$", views.OrgaManualMergeItems.as_view(), name="orga_manual_merge_items", ), - url(r"reset/$", views.reset_wizards, name="reset_wizards"), - url( + re_path(r"reset/$", views.reset_wizards, name="reset_wizards"), + re_path( r"activate-all-search/$", views.activate_all_search, name="activate-all-search" ), - url( + re_path( r"activate-own-search/$", views.activate_own_search, name="activate-own-search" ), - url( + re_path( r"activate-advanced-menu/$", views.activate_advanced_shortcut_menu, name="activate-advanced-menu", ), - url( + re_path( r"activate-simple-menu/$", views.activate_simple_shortcut_menu, name="activate-simple-menu", ), - url(r"hide-shortcut-menu/$", views.hide_shortcut_menu, name="hide-shortcut-menu"), - url(r"show-shortcut-menu/$", views.show_shortcut_menu, name="show-shortcut-menu"), - url( + re_path(r"hide-shortcut-menu/$", views.hide_shortcut_menu, name="hide-shortcut-menu"), + re_path(r"show-shortcut-menu/$", views.show_shortcut_menu, name="show-shortcut-menu"), + re_path( r"regenerate-external-id/$", views.regenerate_external_id, name="regenerate-external-id", @@ -617,66 +617,66 @@ urlpatterns += [ views.regenerate_permissions, name="regenerate-permissions", ), - url( + re_path( r"document/search/(?P<step>.+)?$", check_permissions( ["ishtar_common.view_document", "ishtar_common.view_own_document"] )(views.document_search_wizard), name="search-document", ), - url( + re_path( r"document/search/(?P<step>.+)?$", check_permissions( ["ishtar_common.view_document", "ishtar_common.view_own_document"] )(views.document_search_wizard), name="document_search", ), - url( + re_path( r"document/create/$", check_permissions( ["ishtar_common.add_document"] )(views.DocumentCreateView.as_view()), name="create-document", ), - url( + re_path( r"document/edit/$", check_permissions( ["ishtar_common.change_document", "ishtar_common.change_own_document"] )(views.DocumentSelectView.as_view()), name="edit-document", ), - url( + re_path( r"document/edit/(?P<pk>.+)/$", check_permissions( ["ishtar_common.change_document", "ishtar_common.change_own_document"] )(views.DocumentEditView.as_view()), name="edit-document", ), - url( + re_path( r"document/delete/(?P<step>.+)?$", check_permissions( ["ishtar_common.delete_document", "ishtar_common.delete_own_document"] )(views.document_deletion_wizard), name="document_deletion", ), - url( + re_path( r"autocomplete-document/$", views.autocomplete_document, name="autocomplete-document", ), - url( + re_path( r"document/shortcut/delete/(?P<pk>.+)/$", views.document_delete, name="delete-document", ), - url( + re_path( r"^document-qa-bulk-update/(?P<pks>[0-9-]+)?/$", check_permissions( ["ishtar_common.change_document", "ishtar_common.change_own_document"] )(views.QADocumentForm.as_view()), name="document-qa-bulk-update", ), - url( + re_path( r"^document-qa-bulk-update/(?P<pks>[0-9-]+)?/confirm/$", check_permissions( ["ishtar_common.change_document", "ishtar_common.change_own_document"] @@ -684,7 +684,7 @@ urlpatterns += [ name="document-qa-bulk-update-confirm", kwargs={"confirm": True}, ), - url( + re_path( r"^document-qa-duplicate/(?P<pks>[0-9-]+)?/$", check_permissions( ["ishtar_common.change_document", "ishtar_common.change_own_document"] @@ -698,38 +698,38 @@ urlpatterns += [ )(views.QADocumentUnlink.as_view()), name="document-qa-unlink", ), - url( + re_path( r"^document-qa-packaging/(?P<pks>[0-9-]+)?/$", check_permissions( ["ishtar_common.change_document", "ishtar_common.change_own_document"] )(views.QADocumentPackagingFormView.as_view()), name="document-qa-packaging", ), - url( + re_path( r"autocomplete-documenttag/$", views.autocomplete_documenttag, name="autocomplete-documenttag", ), - url( + re_path( r"new-documenttag/(?:(?P<parent_name>[^/]+)/)?" r"(?:(?P<limits>[^/]+)/)?$", views.new_document_tag, name="new-documenttag", ), - url( + re_path( r"geo/create/(?P<app_source>[-\w]+)/(?P<model_source>[-\w]+)/(?P<source_pk>\d+)/$", check_permissions( ["ishtar_common.add_geovectordata"] )(views.GeoPreCreateView.as_view()), name="create-pre-geo", ), - url( + re_path( r"geo/create/(?P<app_source>[-\w]+)/(?P<model_source>[-\w]+)/(?P<source_pk>\d+)/(?P<geom_type>[-\w]+)/$", check_permissions( ["ishtar_common.add_geovectordata"] )(views.GeoCreateView.as_view()), name="create-geo", ), - url( + re_path( r"geo/edit/(?P<pk>\d+)/$", check_permissions( ["ishtar_common.change_geovectordata", @@ -737,7 +737,7 @@ urlpatterns += [ )(views.GeoEditView.as_view()), name="edit-geo", ), - url( + re_path( r"geo/delete/(?P<pk>\d+)/$", check_permissions( ["ishtar_common.delete_geovectordata", @@ -745,7 +745,7 @@ urlpatterns += [ )(views.GeoDeleteView.as_view()), name="delete-geo", ), - url( + re_path( r"^qa-not-available(?:/(?P<context>[0-9a-z-]+))?/$", views.QANotAvailable.as_view(), name="qa-not-available", @@ -770,7 +770,7 @@ urlpatterns += [ urlpatterns += get_urls_for_model(models.Document, views, own=True) urlpatterns += [ - url(r"(?P<action_slug>" + actions + r")/$", views.action, name="action"), + re_path(r"(?P<action_slug>" + actions + r")/$", views.action, name="action"), ] diff --git a/ishtar_common/urls_registration.py b/ishtar_common/urls_registration.py index 556bf6f95..a3bc5efb1 100644 --- a/ishtar_common/urls_registration.py +++ b/ishtar_common/urls_registration.py @@ -1,5 +1,4 @@ -from django.conf.urls import url -from django.urls import path +from django.urls import path, re_path from django.views.generic.base import TemplateView try: @@ -12,7 +11,8 @@ from django.contrib.auth import views as auth_views from ishtar_common import views urlpatterns = [ - url(r'^accounts/activate/complete/$', + re_path( + r'^accounts/activate/complete/$', TemplateView.as_view( template_name='registration/activation_complete.html' ), @@ -21,23 +21,27 @@ urlpatterns = [ # [a-fA-F0-9]{40} because a bad activation key should still get to # the view; that way it can return a sensible "invalid key" # message instead of a confusing 404. - url(r'^accounts/activate/(?P<activation_key>\w+)/$', + re_path( + r'^accounts/activate/(?P<activation_key>\w+)/$', registration_views.ActivationView.as_view(), name='registration_activate'), - url(r'^accounts/register/$', + re_path( + r'^accounts/register/$', views.RegistrationView.as_view(), name='registration_register'), - url(r'^accounts/register/complete/$', + re_path( + r'^accounts/register/complete/$', TemplateView.as_view( template_name='registration/registration_complete.html' ), name='registration_complete'), - url(r'^accounts/register/closed/$', + re_path( + r'^accounts/register/closed/$', TemplateView.as_view( template_name='registration/registration_closed.html' ), name='registration_disallowed'), - # url("^accounts/", include('django.contrib.auth.urls')), + # re_path("^accounts/", include('django.contrib.auth.urls')), path('accounts/login/', views.LoginView.as_view(), name='login'), path('accounts/logout/', views.LogoutView.as_view(), name='logout'), path('accounts/password_change/', views.PasswordChangeView.as_view(), @@ -45,4 +49,4 @@ urlpatterns = [ path('accounts/password_reset/', views.PasswordResetView.as_view(), name='password_reset'), path('accounts/reset/<uidb64>/<token>/', views.PasswordResetConfirmView.as_view(), name='password_reset_confirm'), -]
\ No newline at end of file +] diff --git a/ishtar_common/utils.py b/ishtar_common/utils.py index 65c0128ab..bd20e4919 100644 --- a/ishtar_common/utils.py +++ b/ishtar_common/utils.py @@ -54,7 +54,6 @@ import zipfile from django import forms from django.apps import apps from django.conf import settings -from django.conf.urls import url from django.contrib.auth.models import Permission, User, Group from django.contrib.auth.hashers import Argon2PasswordHasher as BaseArgon2PasswordHasher from django.contrib.contenttypes.models import ContentType @@ -70,7 +69,7 @@ from django.db import models from django.db.models import Q from django.db.models.functions import Length from django.http import HttpResponseRedirect -from django.urls import reverse, NoReverseMatch +from django.urls import re_path, reverse, NoReverseMatch from django.utils.crypto import get_random_string from django.utils.datastructures import MultiValueDict as BaseMultiValueDict from django.utils.formats import date_format @@ -84,20 +83,20 @@ from .jinja_filters import capfirst_filter, capitalize_filter, \ if settings.USE_TRANSLATION_OVERLOAD: from overload_translation.utils import ( - ugettext_lazy, - ugettext, + gettext_lazy, + gettext, pgettext_lazy, pgettext, ) else: from django.utils.translation import ( - ugettext_lazy, - ugettext, + gettext_lazy, + gettext, pgettext_lazy, pgettext, ) -_ = ugettext_lazy +_ = gettext_lazy logger = logging.getLogger(__name__) @@ -1300,7 +1299,7 @@ def _external_id_changed(sender, **kwargs): def shortify(lbl, number=20): - SHORTIFY_STR = ugettext(" (...)") + SHORTIFY_STR = gettext(" (...)") if not lbl: lbl = "" if len(lbl) <= number: @@ -2301,7 +2300,7 @@ def get_urls_for_model( app_label = model._meta.app_label model_name = model._meta.model_name urls = [ - url( + re_path( r"show-{}(?:/(?P<pk>.+))?/(?P<type>.+)?$".format(model.SLUG), check_permissions( [f"{app_label}.view_{model_name}", @@ -2310,7 +2309,7 @@ def get_urls_for_model( ), name="show-" + model.SLUG, ), - url( + re_path( r"^display-{}/(?P<pk>.+)/$".format(model.SLUG), check_permissions( [f"{app_label}.view_{model_name}", @@ -2322,7 +2321,7 @@ def get_urls_for_model( ] if own: urls += [ - url( + re_path( r"get-{}/own/(?P<type>.+)?$".format(model.SLUG), check_permissions( [f"{app_label}.view_{model_name}", @@ -2335,7 +2334,7 @@ def get_urls_for_model( ] urls += [ - url( + re_path( r"get-{}/(?P<type>.+)?$".format(model.SLUG), check_permissions( [f"{app_label}.view_{model_name}", @@ -2348,7 +2347,7 @@ def get_urls_for_model( if autocomplete: urls += [ - url( + re_path( r"autocomplete-{}/$".format(model.SLUG), check_permissions( [f"{app_label}.view_{model_name}", diff --git a/ishtar_common/utils_migrations.py b/ishtar_common/utils_migrations.py index 21de2fefa..f11428e3c 100644 --- a/ishtar_common/utils_migrations.py +++ b/ishtar_common/utils_migrations.py @@ -8,9 +8,9 @@ import uuid from django.core.files import File from django.core.management import call_command from django.db import connection -from django.utils.translation import ugettext_lazy +from django.utils.translation import gettext_lazy -HOMEPAGE_TITLE = ugettext_lazy("Welcome in Ishtar, open source software for management and inventory of archaeological data") +HOMEPAGE_TITLE = gettext_lazy("Welcome in Ishtar, open source software for management and inventory of archaeological data") def migrations_load_data(module_name, migration_filename): diff --git a/ishtar_common/views.py b/ishtar_common/views.py index a4242aa3b..50c16419c 100644 --- a/ishtar_common/views.py +++ b/ishtar_common/views.py @@ -57,7 +57,7 @@ from django.shortcuts import redirect, render, get_object_or_404 from django.urls import reverse, NoReverseMatch from django.utils import translation from django.utils.decorators import method_decorator -from django.utils.translation import ugettext, ugettext_lazy as _ +from django.utils.translation import gettext, gettext_lazy as _ from django.views.generic import ListView, TemplateView, View from django.views.generic.edit import CreateView, DeleteView, FormView, UpdateView from extra_views import ModelFormSetView @@ -1256,7 +1256,7 @@ def action(request, action_slug, obj_id=None, *args, **kwargs): Action management """ if not check_permission(request, action_slug): - not_permitted_msg = ugettext("Operation not permitted.") + not_permitted_msg = gettext("Operation not permitted.") if obj_id: model_name = action.split('_')[0].split("-")[0].split("/")[0] if model_name not in ACTION_MODEL_DICT: diff --git a/ishtar_common/views_item.py b/ishtar_common/views_item.py index 6c7b85130..95ef1d8ad 100644 --- a/ishtar_common/views_item.py +++ b/ishtar_common/views_item.py @@ -61,8 +61,8 @@ from django.utils.translation import ( deactivate, get_language, pgettext_lazy, - ugettext, - ugettext_lazy as _, + gettext, + gettext_lazy as _, ) from guardian.models import UserObjectPermission from tidylib import tidy_document as tidy @@ -262,7 +262,7 @@ def new_qa_item( callback=None ): def func(request, parent_name=None, limits=""): - not_permitted_msg = ugettext("Operation not permitted.") + not_permitted_msg = gettext("Operation not permitted.") meta = model._meta permission = f"{meta.app_label}.add_{meta.model_name}" if not check_permission(request, permission): @@ -308,7 +308,7 @@ def new_qa_item( def get_short_html_detail(model): def func(request, pk): - not_permitted_msg = ugettext("Operation not permitted.") + not_permitted_msg = gettext("Operation not permitted.") try: item = model.objects.get(pk=pk) except model.DoesNotExist: @@ -327,7 +327,7 @@ def modify_qa_item(model, frm, callback=None): def func(request, parent_name="", pk=None): template = "ishtar/forms/qa_new_item.html" model_name = model._meta.object_name - not_permitted_msg = ugettext("Operation not permitted.") + not_permitted_msg = gettext("Operation not permitted.") try: item = model.objects.get(pk=pk) except model.DoesNotExist: diff --git a/ishtar_common/widgets.py b/ishtar_common/widgets.py index 97ed7deec..1c0b23c13 100644 --- a/ishtar_common/widgets.py +++ b/ishtar_common/widgets.py @@ -38,7 +38,7 @@ from django.utils.functional import lazy from django.utils.html import escape from django.utils.safestring import mark_safe from json import JSONEncoder -from django.utils.translation import ugettext_lazy as _, get_language +from django.utils.translation import gettext_lazy as _, get_language from ishtar_common import models from ishtar_common.utils import get_columns_from_class, reverse_coordinates diff --git a/ishtar_common/wizards.py b/ishtar_common/wizards.py index 1d5e95647..8d58b4146 100644 --- a/ishtar_common/wizards.py +++ b/ishtar_common/wizards.py @@ -47,7 +47,7 @@ from django.http import HttpResponseRedirect, Http404 from django.forms import ValidationError from django.shortcuts import redirect, render, reverse from django.template import loader -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from django.utils.safestring import mark_safe from ishtar_common import models, models_rest |