From eadc06d4c519b594728f844279f282f596078d8e Mon Sep 17 00:00:00 2001 From: Santiago Lamora Date: Wed, 21 Apr 2021 14:27:18 +0200 Subject: [PATCH] django.core.urlresolvers moved to django.urls Django 2.0 --- orchestra/admin/__init__.py | 4 +- orchestra/admin/dashboard.py | 10 +-- orchestra/admin/menu.py | 8 +- orchestra/admin/utils.py | 2 +- orchestra/api/helpers.py | 2 +- orchestra/contrib/accounts/actions.py | 38 ++++---- orchestra/contrib/accounts/admin.py | 50 +++++------ orchestra/contrib/bills/actions.py | 8 +- orchestra/contrib/bills/admin.py | 72 ++++++++-------- orchestra/contrib/bills/filters.py | 28 +++--- orchestra/contrib/bills/helpers.py | 2 +- orchestra/contrib/bills/models.py | 86 +++++++++---------- .../databases/tests/functional_tests/tests.py | 2 +- orchestra/contrib/domains/admin.py | 32 +++---- .../domains/tests/functional_tests/tests.py | 60 ++++++------- orchestra/contrib/history/admin.py | 26 +++--- orchestra/contrib/issues/admin.py | 54 ++++++------ .../lists/tests/functional_tests/tests.py | 2 +- orchestra/contrib/mailboxes/admin.py | 54 ++++++------ .../mailboxes/tests/functional_tests/tests.py | 2 +- orchestra/contrib/mailer/actions.py | 2 +- orchestra/contrib/mailer/admin.py | 26 +++--- orchestra/contrib/miscellaneous/admin.py | 28 +++--- orchestra/contrib/orchestration/helpers.py | 2 +- .../contrib/orchestration/middlewares.py | 20 ++--- orchestra/contrib/orders/actions.py | 10 +-- orchestra/contrib/orders/admin.py | 24 +++--- orchestra/contrib/payments/actions.py | 2 +- orchestra/contrib/payments/admin.py | 34 ++++---- orchestra/contrib/plans/admin.py | 8 +- orchestra/contrib/resources/actions.py | 2 +- orchestra/contrib/resources/admin.py | 44 +++++----- orchestra/contrib/saas/services/phplist.py | 12 +-- orchestra/contrib/services/actions.py | 2 +- orchestra/contrib/services/admin.py | 12 +-- .../tests/functional_tests/tests.py | 2 +- orchestra/contrib/webapps/admin.py | 18 ++-- orchestra/contrib/webapps/types/cms.py | 14 +-- orchestra/contrib/websites/admin.py | 18 ++-- orchestra/models/fields.py | 20 ++--- orchestra/permissions/api.py | 8 +- orchestra/templatetags/utils.py | 4 +- orchestra/utils/tests.py | 2 +- 43 files changed, 428 insertions(+), 428 deletions(-) diff --git a/orchestra/admin/__init__.py b/orchestra/admin/__init__.py index d59c7fab..508aee46 100644 --- a/orchestra/admin/__init__.py +++ b/orchestra/admin/__init__.py @@ -3,7 +3,7 @@ from collections import OrderedDict from functools import update_wrapper from django.contrib import admin -from django.core.urlresolvers import reverse +from django.urls import reverse from django.shortcuts import render, redirect from django.utils.safestring import mark_safe from django.utils.translation import ugettext_lazy as _ @@ -56,7 +56,7 @@ def search(request): if service.search: models.add(service.model) model_name_map[service.model._meta.model_name] = service.model - + # Account direct access if search_term.endswith('!'): from ..contrib.accounts.models import Account diff --git a/orchestra/admin/dashboard.py b/orchestra/admin/dashboard.py index 5cded62c..9237470d 100644 --- a/orchestra/admin/dashboard.py +++ b/orchestra/admin/dashboard.py @@ -1,4 +1,4 @@ -from django.core.urlresolvers import reverse +from django.urls import reverse from django.utils.translation import ugettext_lazy as _ from fluent_dashboard import dashboard, appsettings from fluent_dashboard.modules import CmsAppIconList @@ -11,7 +11,7 @@ class AppDefaultIconList(CmsAppIconList): def __init__(self, *args, **kwargs): self.icons = kwargs.pop('icons') super(AppDefaultIconList, self).__init__(*args, **kwargs) - + def get_icon_for_model(self, app_name, model_name, default=None): icon = self.icons.get('.'.join((app_name, model_name))) return super(AppDefaultIconList, self).get_icon_for_model(app_name, model_name, default=icon) @@ -19,7 +19,7 @@ class AppDefaultIconList(CmsAppIconList): class OrchestraIndexDashboard(dashboard.FluentIndexDashboard): """ Gets application modules from services, accounts and administration registries """ - + def __init__(self, **kwargs): super(dashboard.FluentIndexDashboard, self).__init__(**kwargs) self.children.append(self.get_personal_module()) @@ -27,7 +27,7 @@ class OrchestraIndexDashboard(dashboard.FluentIndexDashboard): recent_actions = self.get_recent_actions_module() recent_actions.enabled = True self.children.append(recent_actions) - + def process_registered_view(self, module, view_name, options): app_name, name = view_name.split('_')[:-1] module.icons['.'.join((app_name, name))] = options.get('icon') @@ -47,7 +47,7 @@ class OrchestraIndexDashboard(dashboard.FluentIndexDashboard): 'title': options.get('verbose_name_plural'), 'url': add_url, }) - + def get_application_modules(self): modules = [] # Honor settings override, hacky. I Know diff --git a/orchestra/admin/menu.py b/orchestra/admin/menu.py index 6f5db81e..1c16f761 100644 --- a/orchestra/admin/menu.py +++ b/orchestra/admin/menu.py @@ -1,7 +1,7 @@ from copy import deepcopy from admin_tools.menu import items, Menu -from django.core.urlresolvers import reverse +from django.urls import reverse from django.utils.text import capfirst from django.utils.translation import ugettext_lazy as _ @@ -16,7 +16,7 @@ def api_link(context): opts = context['cl'].opts else: return reverse('api-root') - if 'object_id' in context: + if 'object_id' in context: object_id = context['object_id'] try: return reverse('%s-detail' % opts.model_name, args=[object_id]) @@ -42,7 +42,7 @@ def process_registry(register): item = items.MenuItem(name, url) item.options = options return item - + childrens = {} for model, options in register.get().items(): if options.get('menu', True): @@ -68,7 +68,7 @@ def process_registry(register): class OrchestraMenu(Menu): template = 'admin/orchestra/menu.html' - + def init_with_context(self, context): self.children = [ # items.MenuItem( diff --git a/orchestra/admin/utils.py b/orchestra/admin/utils.py index 9c485d2a..ccf22b49 100644 --- a/orchestra/admin/utils.py +++ b/orchestra/admin/utils.py @@ -6,7 +6,7 @@ from functools import wraps from django.conf import settings from django.contrib import admin from django.core.exceptions import ObjectDoesNotExist -from django.core.urlresolvers import reverse, NoReverseMatch +from django.urls import reverse, NoReverseMatch from django.db import models from django.shortcuts import redirect from django.utils import timezone diff --git a/orchestra/api/helpers.py b/orchestra/api/helpers.py index 6bc8f749..67594455 100644 --- a/orchestra/api/helpers.py +++ b/orchestra/api/helpers.py @@ -1,4 +1,4 @@ -from django.core.urlresolvers import NoReverseMatch +from django.urls import NoReverseMatch from rest_framework.reverse import reverse diff --git a/orchestra/contrib/accounts/actions.py b/orchestra/contrib/accounts/actions.py index f7f7ba91..1712da8a 100644 --- a/orchestra/contrib/accounts/actions.py +++ b/orchestra/contrib/accounts/actions.py @@ -4,7 +4,7 @@ from django.contrib import messages from django.contrib.admin import helpers from django.contrib.admin.utils import NestedObjects, quote from django.contrib.auth import get_permission_codename -from django.core.urlresolvers import reverse, NoReverseMatch +from django.urls import reverse, NoReverseMatch from django.db import router from django.shortcuts import redirect, render from django.template.response import TemplateResponse @@ -53,14 +53,14 @@ def service_report(modeladmin, request, queryset): fields.append((model, name)) fields = sorted(fields, key=lambda f: f[0]._meta.verbose_name_plural.lower()) fields = [field for model, field in fields] - + for account in queryset.prefetch_related(*fields): items = [] for field in fields: related_manager = getattr(account, field) items.append((related_manager.model._meta, related_manager.all())) accounts.append((account, items)) - + context = { 'accounts': accounts, 'date': timezone.now().today() @@ -71,21 +71,21 @@ def service_report(modeladmin, request, queryset): def delete_related_services(modeladmin, request, queryset): opts = modeladmin.model._meta app_label = opts.app_label - + using = router.db_for_write(modeladmin.model) collector = NestedObjects(using=using) collector.collect(queryset) registered_services = services.get() related_services = [] to_delete = [] - + admin_site = modeladmin.admin_site - + def format(obj, account=False): has_admin = obj.__class__ in admin_site._registry opts = obj._meta no_edit_link = '%s: %s' % (capfirst(opts.verbose_name), force_text(obj)) - + if has_admin: try: admin_url = reverse( @@ -95,7 +95,7 @@ def delete_related_services(modeladmin, request, queryset): except NoReverseMatch: # Change url doesn't exist -- don't display link to edit return no_edit_link - + # Display a link to the admin page. context = (capfirst(opts.verbose_name), admin_url, obj) if account: @@ -106,7 +106,7 @@ def delete_related_services(modeladmin, request, queryset): # Don't display link to edit, because it either has no # admin or is edited inline. return no_edit_link - + def format_nested(objs, result): if isinstance(objs, list): current = [] @@ -115,7 +115,7 @@ def delete_related_services(modeladmin, request, queryset): result.append(current) else: result.append(format(objs)) - + for nested in collector.nested(): if isinstance(nested, list): # Is lists of objects @@ -141,7 +141,7 @@ def delete_related_services(modeladmin, request, queryset): # Prevent the deletion of the main system user, which will delete the account main_systemuser = nested.main_systemuser related_services.append(format(nested, account=True)) - + # The user has already confirmed the deletion. # Do the deletion and return a None to display the change list view again. if request.POST.get('post'): @@ -165,12 +165,12 @@ def delete_related_services(modeladmin, request, queryset): modeladmin.message_user(request, msg, messages.SUCCESS) # Return None to display the change list page again. return None - + if len(queryset) == 1: objects_name = force_text(opts.verbose_name) else: objects_name = force_text(opts.verbose_name_plural) - + model_count = {} for model, objs in collector.model_objs.items(): count = 0 @@ -220,10 +220,10 @@ def disable_selected(modeladmin, request, queryset, disable=True): n) ) return None - + user = request.user admin_site = modeladmin.admin_site - + def format(obj): has_admin = obj.__class__ in admin_site._registry opts = obj._meta @@ -238,7 +238,7 @@ def disable_selected(modeladmin, request, queryset, disable=True): except NoReverseMatch: # Change url doesn't exist -- don't display link to edit return no_edit_link - + p = '%s.%s' % (opts.app_label, get_permission_codename('delete', opts)) if not user.has_perm(p): perms_needed.add(opts.verbose_name) @@ -249,19 +249,19 @@ def disable_selected(modeladmin, request, queryset, disable=True): # Don't display link to edit, because it either has no # admin or is edited inline. return no_edit_link - + display = [] for account in queryset: current = [] for related in account.get_services_to_disable(): current.append(format(related)) display.append([format(account), current]) - + if len(queryset) == 1: objects_name = force_text(opts.verbose_name) else: objects_name = force_text(opts.verbose_name_plural) - + context = dict( admin_site.each_context(request), action_name='disable_selected' if disable else 'enable_selected', diff --git a/orchestra/contrib/accounts/admin.py b/orchestra/contrib/accounts/admin.py index b2e7973b..2008fb6b 100644 --- a/orchestra/contrib/accounts/admin.py +++ b/orchestra/contrib/accounts/admin.py @@ -8,7 +8,7 @@ from django.conf.urls import url from django.contrib import admin, messages from django.contrib.admin.utils import unquote from django.contrib.auth import admin as auth -from django.core.urlresolvers import reverse +from django.urls import reverse from django.http import HttpResponseRedirect from django.templatetags.static import static from django.utils.safestring import mark_safe @@ -71,15 +71,15 @@ class AccountAdmin(ChangePasswordAdminMixin, auth.UserAdmin, ExtendedModelAdmin) ) change_view_actions = (disable_selected, service_report, enable_selected) ordering = () - + main_systemuser_link = admin_link('main_systemuser') - + def formfield_for_dbfield(self, db_field, **kwargs): """ Make value input widget bigger """ if db_field.name == 'comments': kwargs['widget'] = forms.Textarea(attrs={'cols': 70, 'rows': 4}) return super(AccountAdmin, self).formfield_for_dbfield(db_field, **kwargs) - + def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None): if not add: if request.method == 'GET' and not obj.is_active: @@ -96,7 +96,7 @@ class AccountAdmin(ChangePasswordAdminMixin, auth.UserAdmin, ExtendedModelAdmin) }) return super(AccountAdmin, self).render_change_form( request, context, add, change, form_url, obj) - + def get_fieldsets(self, request, obj=None): fieldsets = super(AccountAdmin, self).get_fieldsets(request, obj) if not obj: @@ -106,7 +106,7 @@ class AccountAdmin(ChangePasswordAdminMixin, auth.UserAdmin, ExtendedModelAdmin) fieldsets = list(fieldsets) fieldsets.insert(1, (_("Related services"), {'fields': fields})) return fieldsets - + def save_model(self, request, obj, form, change): if not change: form.save_model(obj) @@ -133,7 +133,7 @@ class AccountAdmin(ChangePasswordAdminMixin, auth.UserAdmin, ExtendedModelAdmin) if msg: messages.warning(request, mark_safe(msg % context)) super(AccountAdmin, self).save_model(request, obj, form, change) - + def get_change_view_actions(self, obj=None): views = super().get_change_view_actions(obj=obj) if obj is not None: @@ -141,7 +141,7 @@ class AccountAdmin(ChangePasswordAdminMixin, auth.UserAdmin, ExtendedModelAdmin) return [view for view in views if view.url_name != 'enable'] return [view for view in views if view.url_name != 'disable'] return views - + def get_actions(self, request): actions = super().get_actions(request) if 'delete_selected' in actions: @@ -157,7 +157,7 @@ class AccountListAdmin(AccountAdmin): list_display = ('select_account', 'username', 'type', 'username') actions = None change_list_template = 'admin/accounts/account/select_account_list.html' - + def select_account(self, instance): # TODO get query string from request.META['QUERY_STRING'] to preserve filters context = { @@ -169,7 +169,7 @@ class AccountListAdmin(AccountAdmin): select_account.short_description = _("account") select_account.allow_tags = True select_account.admin_order_field = 'username' - + def changelist_view(self, request, extra_context=None): app_label = request.META['PATH_INFO'].split('/')[-5] model = request.META['PATH_INFO'].split('/')[-4] @@ -206,7 +206,7 @@ class AccountAdminMixin(object): change_form_template = 'admin/accounts/account/change_form.html' account = None list_select_related = ('account',) - + def display_active(self, instance): if not instance.is_active: return 'False' % static('admin/img/icon-no.svg') @@ -217,14 +217,14 @@ class AccountAdminMixin(object): display_active.short_description = _("active") display_active.allow_tags = True display_active.admin_order_field = 'is_active' - + def account_link(self, instance): account = instance.account if instance.pk else self.account return admin_link()(account) account_link.short_description = _("account") account_link.allow_tags = True account_link.admin_order_field = 'account__username' - + def get_form(self, request, obj=None, **kwargs): """ Warns user when object's account is disabled """ form = super(AccountAdminMixin, self).get_form(request, obj, **kwargs) @@ -247,7 +247,7 @@ class AccountAdminMixin(object): # Not available in POST form.initial_account = self.get_changeform_initial_data(request).get('account') return form - + def get_fields(self, request, obj=None): """ remove account or account_link depending on the case """ fields = super(AccountAdminMixin, self).get_fields(request, obj) @@ -263,13 +263,13 @@ class AccountAdminMixin(object): except ValueError: pass return fields - + def get_readonly_fields(self, request, obj=None): """ provide account for filter_by_account_fields """ if obj: self.account = obj.account return super(AccountAdminMixin, self).get_readonly_fields(request, obj) - + def formfield_for_dbfield(self, db_field, **kwargs): """ Filter by account """ formfield = super(AccountAdminMixin, self).formfield_for_dbfield(db_field, **kwargs) @@ -277,14 +277,14 @@ class AccountAdminMixin(object): if self.account: # Hack widget render in order to append ?account=id to the add url old_render = formfield.widget.render - + def render(*args, **kwargs): output = old_render(*args, **kwargs) output = output.replace('/add/"', '/add/?account=%s"' % self.account.pk) with_qargs = r'/add/?\1&account=%s"' % self.account.pk output = re.sub(r'/add/\?([^".]*)"', with_qargs, output) return mark_safe(output) - + formfield.widget.render = render # Filter related object by account formfield.queryset = formfield.queryset.filter(account=self.account) @@ -302,21 +302,21 @@ class AccountAdminMixin(object): formfield.initial = 1 formfield.queryset = formfield.queryset.order_by('username') return formfield - + def get_formset(self, request, obj=None, **kwargs): """ provides form.account for convinience """ formset = super(AccountAdminMixin, self).get_formset(request, obj, **kwargs) formset.form.account = self.account formset.account = self.account return formset - + def get_account_from_preserve_filters(self, request): preserved_filters = self.get_preserved_filters(request) preserved_filters = dict(parse_qsl(preserved_filters)) cl_filters = preserved_filters.get('_changelist_filters') if cl_filters: return dict(parse_qsl(cl_filters)).get('account') - + def changeform_view(self, request, object_id=None, form_url='', extra_context=None): account_id = self.get_account_from_preserve_filters(request) if not object_id: @@ -331,7 +331,7 @@ class AccountAdminMixin(object): context.update(extra_context or {}) return super(AccountAdminMixin, self).changeform_view( request, object_id, form_url=form_url, extra_context=context) - + def changelist_view(self, request, extra_context=None): account_id = request.GET.get('account') context = {} @@ -367,7 +367,7 @@ class SelectAccountAdminMixin(AccountAdminMixin): account = Account.objects.get(pk=request.GET['account']) [setattr(inline, 'account', account) for inline in inlines] return inlines - + def get_urls(self): """ Hooks select account url """ urls = super(AccountAdminMixin, self).get_urls() @@ -381,7 +381,7 @@ class SelectAccountAdminMixin(AccountAdminMixin): name='%s_%s_select_account' % info), ] return select_urls + urls - + def add_view(self, request, form_url='', extra_context=None): """ Redirects to select account view if required """ if request.user.is_superuser: @@ -406,7 +406,7 @@ class SelectAccountAdminMixin(AccountAdminMixin): return super(AccountAdminMixin, self).add_view( request, form_url=form_url, extra_context=context) return HttpResponseRedirect('./select-account/?%s' % request.META['QUERY_STRING']) - + def save_model(self, request, obj, form, change): """ Given a model instance save it to the database. diff --git a/orchestra/contrib/bills/actions.py b/orchestra/contrib/bills/actions.py index dc36938b..37723b42 100644 --- a/orchestra/contrib/bills/actions.py +++ b/orchestra/contrib/bills/actions.py @@ -5,7 +5,7 @@ from datetime import date from django.contrib import messages from django.contrib.admin import helpers from django.core.exceptions import ValidationError -from django.core.urlresolvers import reverse +from django.urls import reverse from django.db import transaction from django.forms.models import modelformset_factory from django.http import HttpResponse, HttpResponseRedirect @@ -179,7 +179,7 @@ def undo_billing(modeladmin, request, queryset): group[line.order].append(line) except KeyError: group[line.order] = [line] - + # Validate for order, lines in group.items(): prev = None @@ -211,7 +211,7 @@ def undo_billing(modeladmin, request, queryset): messages.error(request, "Order does not have lines!.") order.billed_until = billed_until order.billed_on = billed_on - + # Commit changes norders, nlines = 0, 0 for order, lines in group.items(): @@ -221,7 +221,7 @@ def undo_billing(modeladmin, request, queryset): # TODO update order history undo billing order.save(update_fields=('billed_until', 'billed_on')) norders += 1 - + messages.success(request, _("%(norders)s orders and %(nlines)s lines undoed.") % { 'nlines': nlines, 'norders': norders diff --git a/orchestra/contrib/bills/admin.py b/orchestra/contrib/bills/admin.py index befd2235..560819c8 100644 --- a/orchestra/contrib/bills/admin.py +++ b/orchestra/contrib/bills/admin.py @@ -2,7 +2,7 @@ from django import forms from django.conf.urls import url from django.contrib import admin, messages from django.contrib.admin.utils import unquote -from django.core.urlresolvers import reverse +from django.urls import reverse from django.db import models from django.db.models import F, Sum, Prefetch from django.db.models.functions import Coalesce @@ -39,18 +39,18 @@ PAYMENT_STATE_COLORS = { class BillSublineInline(admin.TabularInline): model = BillSubline fields = ('description', 'total', 'type') - + def get_readonly_fields(self, request, obj=None): fields = super().get_readonly_fields(request, obj) if obj and not obj.bill.is_open: return self.get_fields(request) return fields - + def get_max_num(self, request, obj=None): if obj and not obj.bill.is_open: return 0 return super().get_max_num(request, obj) - + def has_delete_permission(self, request, obj=None): if obj and not obj.bill.is_open: return False @@ -64,9 +64,9 @@ class BillLineInline(admin.TabularInline): 'subtotal', 'display_total', ) readonly_fields = ('display_total', 'order_link') - + order_link = admin_link('order', display='pk') - + def display_total(self, line): if line.pk: total = line.compute_total() @@ -79,7 +79,7 @@ class BillLineInline(admin.TabularInline): return '%s' % (url, total) display_total.short_description = _("Total") display_total.allow_tags = True - + def formfield_for_dbfield(self, db_field, **kwargs): """ Make value input widget bigger """ if db_field.name == 'description': @@ -87,7 +87,7 @@ class BillLineInline(admin.TabularInline): elif db_field.name not in ('start_on', 'end_on'): kwargs['widget'] = forms.TextInput(attrs={'size':'6'}) return super().formfield_for_dbfield(db_field, **kwargs) - + def get_queryset(self, request): qs = super().get_queryset(request) return qs.prefetch_related('sublines').select_related('order') @@ -96,14 +96,14 @@ class BillLineInline(admin.TabularInline): class ClosedBillLineInline(BillLineInline): # TODO reimplement as nested inlines when upstream # https://code.djangoproject.com/ticket/9025 - + fields = ( 'display_description', 'order_link', 'start_on', 'end_on', 'rate', 'quantity', 'tax', 'display_subtotal', 'display_total' ) readonly_fields = fields can_delete = False - + def display_description(self, line): descriptions = [line.description] for subline in line.sublines.all(): @@ -111,7 +111,7 @@ class ClosedBillLineInline(BillLineInline): return '
'.join(descriptions) display_description.short_description = _("Description") display_description.allow_tags = True - + def display_subtotal(self, line): subtotals = [' ' + str(line.subtotal)] for subline in line.sublines.all(): @@ -119,13 +119,13 @@ class ClosedBillLineInline(BillLineInline): return '
'.join(subtotals) display_subtotal.short_description = _("Subtotal") display_subtotal.allow_tags = True - + def display_total(self, line): if line.pk: return line.compute_total() display_total.short_description = _("Total") display_total.allow_tags = True - + def has_add_permission(self, request): return False @@ -158,28 +158,28 @@ class BillLineAdmin(admin.ModelAdmin): list_select_related = ('bill', 'bill__account') search_fields = ('description', 'bill__number') inlines = (BillSublineInline,) - + account_link = admin_link('bill__account') bill_link = admin_link('bill') order_link = admin_link('order') amended_line_link = admin_link('amended_line') - + def display_is_open(self, instance): return instance.bill.is_open display_is_open.short_description = _("Is open") display_is_open.boolean = True - + def display_sublinetotal(self, instance): total = instance.subline_total return total if total is not None else '---' display_sublinetotal.short_description = _("Sublines") display_sublinetotal.admin_order_field = 'subline_total' - + def display_total(self, instance): return round(instance.computed_total or 0, 2) display_total.short_description = _("Total") display_total.admin_order_field = 'computed_total' - + def get_readonly_fields(self, request, obj=None): fields = super().get_readonly_fields(request, obj) if obj and not obj.bill.is_open: @@ -188,7 +188,7 @@ class BillLineAdmin(admin.ModelAdmin): 'subtotal', 'order_billed_on', 'order_billed_until' ] return fields - + def get_queryset(self, request): qs = super().get_queryset(request) qs = qs.annotate( @@ -196,7 +196,7 @@ class BillLineAdmin(admin.ModelAdmin): computed_total=(F('subtotal') + Sum(Coalesce('sublines__total', 0))) * (1+F('tax')/100), ) return qs - + def has_delete_permission(self, request, obj=None): if obj and not obj.bill.is_open: return False @@ -209,7 +209,7 @@ class BillLineManagerAdmin(BillLineAdmin): if self.bill_ids: return qset.filter(bill_id__in=self.bill_ids) return qset - + def changelist_view(self, request, extra_context=None): GET_copy = request.GET.copy() bill_ids = GET_copy.pop('ids', None) @@ -304,9 +304,9 @@ class AmendInline(BillAdminMixin, admin.TabularInline): verbose_name_plural = _("Amends") can_delete = False extra = 0 - + self_link = admin_link('__str__') - + def has_add_permission(self, *args, **kwargs): return False @@ -354,12 +354,12 @@ class BillAdmin(BillAdminMixin, ExtendedModelAdmin): 'closed_on_display', 'updated_on_display', 'display_total_with_subtotals', ) date_hierarchy = 'closed_on' - + created_on_display = admin_date('created_on', short_description=_("Created")) closed_on_display = admin_date('closed_on', short_description=_("Closed")) updated_on_display = admin_date('updated_on', short_description=_("Updated")) amend_of_link = admin_link('amend_of') - + # def amend_links(self, bill): # links = [] # for amend in bill.amends.all(): @@ -368,19 +368,19 @@ class BillAdmin(BillAdminMixin, ExtendedModelAdmin): # return '
'.join(links) # amend_links.short_description = _("Amends") # amend_links.allow_tags = True - + def num_lines(self, bill): return bill.lines__count num_lines.admin_order_field = 'lines__count' num_lines.short_description = _("lines") - + def display_total(self, bill): currency = settings.BILLS_CURRENCY.lower() return '%s &%s;' % (bill.compute_total(), currency) display_total.allow_tags = True display_total.short_description = _("total") display_total.admin_order_field = 'approx_total' - + def type_link(self, bill): bill_type = bill.type.lower() url = reverse('admin:bills_%s_changelist' % bill_type) @@ -388,7 +388,7 @@ class BillAdmin(BillAdminMixin, ExtendedModelAdmin): type_link.allow_tags = True type_link.short_description = _("type") type_link.admin_order_field = 'type' - + def get_urls(self): """ Hook bill lines management URLs on bill admin """ urls = super().get_urls() @@ -399,13 +399,13 @@ class BillAdmin(BillAdminMixin, ExtendedModelAdmin): name='bills_bill_manage_lines'), ] return extra_urls + urls - + def get_readonly_fields(self, request, obj=None): fields = super().get_readonly_fields(request, obj) if obj and not obj.is_open: fields += self.add_fields return fields - + def get_fieldsets(self, request, obj=None): fieldsets = super().get_fieldsets(request, obj) if obj: @@ -418,7 +418,7 @@ class BillAdmin(BillAdminMixin, ExtendedModelAdmin): if obj.is_open: fieldsets = fieldsets[0:-1] return fieldsets - + def get_change_view_actions(self, obj=None): actions = super().get_change_view_actions(obj) exclude = [] @@ -428,7 +428,7 @@ class BillAdmin(BillAdminMixin, ExtendedModelAdmin): if obj.type not in obj.AMEND_MAP: exclude += ['amend_bills'] return [action for action in actions if action.__name__ not in exclude] - + def get_inline_instances(self, request, obj=None): cls = type(self) if obj and not obj.is_open: @@ -439,7 +439,7 @@ class BillAdmin(BillAdminMixin, ExtendedModelAdmin): else: cls.inlines = [BillLineInline] return super().get_inline_instances(request, obj) - + def formfield_for_dbfield(self, db_field, **kwargs): """ Make value input widget bigger """ if db_field.name == 'comments': @@ -450,7 +450,7 @@ class BillAdmin(BillAdminMixin, ExtendedModelAdmin): if db_field.name == 'amend_of': formfield.queryset = formfield.queryset.filter(is_open=False) return formfield - + def change_view(self, request, object_id, **kwargs): # TODO raise404, here and everywhere bill = self.get_object(request, unquote(object_id)) @@ -471,7 +471,7 @@ admin.site.register(BillLine, BillLineAdmin) class BillContactInline(admin.StackedInline): model = BillContact fields = ('name', 'address', ('city', 'zipcode'), 'country', 'vat') - + def formfield_for_dbfield(self, db_field, **kwargs): """ Make value input widget bigger """ if db_field.name == 'name': diff --git a/orchestra/contrib/bills/filters.py b/orchestra/contrib/bills/filters.py index de45ca37..a4beb32f 100644 --- a/orchestra/contrib/bills/filters.py +++ b/orchestra/contrib/bills/filters.py @@ -1,5 +1,5 @@ from django.contrib.admin import SimpleListFilter -from django.core.urlresolvers import reverse +from django.urls import reverse from django.db.models import Q from django.utils.safestring import mark_safe from django.utils.translation import ugettext_lazy as _ @@ -11,11 +11,11 @@ class BillTypeListFilter(SimpleListFilter): """ Filter tickets by created_by according to request.user """ title = 'Type' parameter_name = '' - + def __init__(self, request, *args, **kwargs): super(BillTypeListFilter, self).__init__(request, *args, **kwargs) self.request = request - + def lookups(self, request, model_admin): return ( ('bill', _("All")), @@ -25,13 +25,13 @@ class BillTypeListFilter(SimpleListFilter): ('amendmentfee', _("Amendment fee")), ('amendmentinvoice', _("Amendment invoice")), ) - + def queryset(self, request, queryset): return queryset - + def value(self): return self.request.path.split('/')[-2] - + def choices(self, cl): query = self.request.GET.urlencode() for lookup, title in self.lookup_choices: @@ -45,7 +45,7 @@ class BillTypeListFilter(SimpleListFilter): class TotalListFilter(SimpleListFilter): title = _("total") parameter_name = 'total' - + def lookups(self, request, model_admin): return ( ('gt', mark_safe("total > 0")), @@ -53,7 +53,7 @@ class TotalListFilter(SimpleListFilter): ('eq', "total = 0"), ('ne', mark_safe("total ≠ 0")), ) - + def queryset(self, request, queryset): if self.value() == 'gt': return queryset.filter(approx_total__gt=0) @@ -70,13 +70,13 @@ class HasBillContactListFilter(SimpleListFilter): """ Filter Nodes by group according to request.user """ title = _("has bill contact") parameter_name = 'bill' - + def lookups(self, request, model_admin): return ( ('True', _("Yes")), ('False', _("No")), ) - + def queryset(self, request, queryset): if self.value() == 'True': return queryset.filter(billcontact__isnull=False) @@ -87,7 +87,7 @@ class HasBillContactListFilter(SimpleListFilter): class PaymentStateListFilter(SimpleListFilter): title = _("payment state") parameter_name = 'payment_state' - + def lookups(self, request, model_admin): return ( ('OPEN', _("Open")), @@ -95,7 +95,7 @@ class PaymentStateListFilter(SimpleListFilter): ('PENDING', _("Pending")), ('BAD_DEBT', _("Bad debt")), ) - + def queryset(self, request, queryset): # FIXME use queryset.computed_total instead of approx_total, bills.admin.BillAdmin.get_queryset Transaction = queryset.model.transactions.field.remote_field.related_model @@ -137,7 +137,7 @@ class PaymentStateListFilter(SimpleListFilter): class AmendedListFilter(SimpleListFilter): title = _("amended") parameter_name = 'amended' - + def lookups(self, request, model_admin): return ( ('3', _("Closed amends")), @@ -145,7 +145,7 @@ class AmendedListFilter(SimpleListFilter): ('1', _("Any amends")), ('0', _("No amends")), ) - + def queryset(self, request, queryset): if self.value() is None: return queryset diff --git a/orchestra/contrib/bills/helpers.py b/orchestra/contrib/bills/helpers.py index 99fc3319..7efbd610 100644 --- a/orchestra/contrib/bills/helpers.py +++ b/orchestra/contrib/bills/helpers.py @@ -1,5 +1,5 @@ from django.contrib import messages -from django.core.urlresolvers import reverse +from django.urls import reverse from django.utils.encoding import force_text from django.utils.html import format_html from django.utils.safestring import mark_safe diff --git a/orchestra/contrib/bills/models.py b/orchestra/contrib/bills/models.py index eb90776f..da79ec08 100644 --- a/orchestra/contrib/bills/models.py +++ b/orchestra/contrib/bills/models.py @@ -1,7 +1,7 @@ import datetime from dateutil.relativedelta import relativedelta -from django.core.urlresolvers import reverse +from django.urls import reverse from django.core.validators import ValidationError, RegexValidator from django.db import models from django.db.models import F, Sum @@ -36,13 +36,13 @@ class BillContact(models.Model): choices=settings.BILLS_CONTACT_COUNTRIES, default=settings.BILLS_CONTACT_DEFAULT_COUNTRY) vat = models.CharField(_("VAT number"), max_length=64) - + def __str__(self): return self.name - + def get_name(self): return self.name or self.account.get_full_name() - + def clean(self): self.vat = self.vat.strip() self.city = self.city.strip() @@ -99,7 +99,7 @@ class Bill(models.Model): INVOICE: AMENDMENTINVOICE, FEE: AMENDMENTFEE, } - + number = models.CharField(_("number"), max_length=16, unique=True, blank=True) account = models.ForeignKey('accounts.Account', verbose_name=_("account"), related_name='%(class)s') @@ -115,37 +115,37 @@ class Bill(models.Model): # total = models.DecimalField(max_digits=12, decimal_places=2, null=True) comments = models.TextField(_("comments"), blank=True) html = models.TextField(_("HTML"), blank=True) - + objects = BillManager() - + class Meta: get_latest_by = 'id' - + def __str__(self): return self.number - + @classmethod def get_class_type(cls): if cls is models.DEFERRED: cls = cls.__base__ return cls.__name__.upper() - + @cached_property def total(self): return self.compute_total() - + @cached_property def seller(self): return Account.objects.get_main().billcontact - + @cached_property def buyer(self): return self.account.billcontact - + @property def has_multiple_pages(self): return self.type != self.FEE - + @cached_property def payment_state(self): if self.is_open or self.get_type() == self.PROFORMA: @@ -192,7 +192,7 @@ class Bill(models.Model): elif executed: return self.EXECUTED return self.BAD_DEBT - + def clean(self): if self.amend_of_id: errors = {} @@ -206,27 +206,27 @@ class Bill(models.Model): errors['amend_of'] = _("Related invoice is an amendment.") if errors: raise ValidationError(errors) - + def get_payment_state_display(self): value = self.payment_state return force_text(dict(self.PAYMENT_STATES).get(value, value)) - + def get_current_transaction(self): return self.transactions.exclude_rejected().first() - + def get_type(self): return self.type or self.get_class_type() - + @property def is_amend(self): return self.type in self.AMEND_MAP.values() - + def get_amend_type(self): amend_type = self.AMEND_MAP.get(self.type) if amend_type is None: raise TypeError("%s has no associated amend type." % self.type) return amend_type - + def get_number(self): cls = type(self) if cls is models.DEFERRED: @@ -250,16 +250,16 @@ class Bill(models.Model): zeros = (number_length - len(str(number))) * '0' number = zeros + str(number) return '{prefix}{year}{number}'.format(prefix=prefix, year=year, number=number) - + def get_due_date(self, payment=None): now = timezone.now() if payment: return now + payment.get_due_delta() return now + relativedelta(months=1) - + def get_absolute_url(self): return reverse('admin:bills_bill_view', args=(self.pk,)) - + def close(self, payment=False): if not self.is_open: raise TypeError("Bill not in Open state.") @@ -278,10 +278,10 @@ class Bill(models.Model): self.html = self.render(payment=payment) self.save() return transaction - + def get_billing_contact_emails(self): return self.account.get_contacts_emails(usages=(Contact.BILLING,)) - + def send(self): pdf = self.as_pdf() self.account.send_email( @@ -298,7 +298,7 @@ class Bill(models.Model): ) self.is_sent = True self.save(update_fields=['is_sent']) - + def render(self, payment=False, language=None): with translation.override(language or self.account.language): if payment is False: @@ -325,22 +325,22 @@ class Bill(models.Model): html = bill_template.render(context) html = html.replace('-pageskip-', '') return html - + def as_pdf(self): html = self.html or self.render() return html_to_pdf(html, pagination=self.has_multiple_pages) - + def updated(self): self.updated_on = timezone.now() self.save(update_fields=('updated_on',)) - + def save(self, *args, **kwargs): if not self.type: self.type = self.get_type() if not self.number: self.number = self.get_number() super(Bill, self).save(*args, **kwargs) - + @cached def compute_subtotals(self): subtotals = {} @@ -354,21 +354,21 @@ class Bill(models.Model): for tax, subtotal in subtotals.items(): result[tax] = [subtotal, round(tax/100*subtotal, 2)] return result - + @cached def compute_base(self): bases = self.lines.annotate( bases=F('subtotal') + Sum(Coalesce('sublines__total', 0)) ) return round(bases.aggregate(Sum('bases'))['bases__sum'] or 0, 2) - + @cached def compute_tax(self): taxes = self.lines.annotate( taxes=(F('subtotal') + Coalesce(Sum('sublines__total'), 0)) * (F('tax')/100) ) return round(taxes.aggregate(Sum('taxes'))['taxes__sum'] or 0, 2) - + @cached def compute_total(self): if 'lines' in getattr(self, '_prefetched_objects_cache', ()): @@ -435,23 +435,23 @@ class BillLine(models.Model): # Amendment amended_line = models.ForeignKey('self', verbose_name=_("amended line"), related_name='amendment_lines', null=True, blank=True) - + class Meta: get_latest_by = 'id' - + def __str__(self): return "#%i" % self.pk if self.pk else self.description - + def get_verbose_quantity(self): return self.verbose_quantity or self.quantity - + def clean(self): if not self.verbose_quantity: quantity = str(self.quantity) # Strip trailing zeros if quantity.endswith('0'): self.verbose_quantity = quantity.strip('0').strip('.') - + def get_verbose_period(self): from django.template.defaultfilters import date date_format = "N 'y" @@ -467,7 +467,7 @@ class BillLine(models.Model): if ini == end: return ini return "{ini} / {end}".format(ini=ini, end=end) - + @cached def compute_total(self): total = self.subtotal or 0 @@ -478,7 +478,7 @@ class BillLine(models.Model): else: total += self.sublines.aggregate(sub_total=Sum('total'))['sub_total'] or 0 return round(total, 2) - + def get_absolute_url(self): return change_url(self) @@ -493,12 +493,12 @@ class BillSubline(models.Model): (COMPENSATION, _("Compensation")), (OTHER, _("Other")), ) - + # TODO: order info for undoing line = models.ForeignKey(BillLine, verbose_name=_("bill line"), related_name='sublines') description = models.CharField(_("description"), max_length=256) total = models.DecimalField(max_digits=12, decimal_places=2) type = models.CharField(_("type"), max_length=16, choices=TYPES, default=OTHER) - + def __str__(self): return "%s %i" % (self.description, self.total) diff --git a/orchestra/contrib/databases/tests/functional_tests/tests.py b/orchestra/contrib/databases/tests/functional_tests/tests.py index 55bef281..3d89bff1 100644 --- a/orchestra/contrib/databases/tests/functional_tests/tests.py +++ b/orchestra/contrib/databases/tests/functional_tests/tests.py @@ -6,7 +6,7 @@ import unittest import MySQLdb from django.conf import settings as djsettings from django.core.management.base import CommandError -from django.core.urlresolvers import reverse +from django.urls import reverse from orchestra.admin.utils import change_url from orchestra.contrib.orchestration.models import Route, Server from orchestra.utils.sys import sshrun diff --git a/orchestra/contrib/domains/admin.py b/orchestra/contrib/domains/admin.py index af054de4..47b5e14d 100644 --- a/orchestra/contrib/domains/admin.py +++ b/orchestra/contrib/domains/admin.py @@ -1,5 +1,5 @@ from django.contrib import admin -from django.core.urlresolvers import reverse +from django.urls import reverse from django.db import models from django.db.models.functions import Concat, Coalesce from django.templatetags.static import static @@ -32,18 +32,18 @@ class DomainInline(admin.TabularInline): readonly_fields = ('domain_link', 'display_records', 'account_link') extra = 0 verbose_name_plural = _("Subdomains") - + domain_link = admin_link('__str__') domain_link.short_description = _("Name") account_link = admin_link('account') - + def display_records(self, domain): return ', '.join([record.type for record in domain.records.all()]) display_records.short_description = _("Declared records") - + def has_add_permission(self, *args, **kwargs): return False - + def get_queryset(self, request): """ Order by structured name and imporve performance """ qs = super(DomainInline, self).get_queryset(request) @@ -66,9 +66,9 @@ class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin): add_form = BatchDomainCreationAdminForm actions = (edit_records, set_soa, list_accounts) change_view_actions = (view_zone, edit_records) - + top_link = admin_link('top') - + def structured_name(self, domain): if domain.is_top: return domain.name @@ -76,13 +76,13 @@ class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin): structured_name.short_description = _("name") structured_name.allow_tags = True structured_name.admin_order_field = 'structured_name' - + def display_is_top(self, domain): return domain.is_top display_is_top.short_description = _("Is top") display_is_top.boolean = True display_is_top.admin_order_field = 'top' - + def display_websites(self, domain): if apps.isinstalled('orchestra.contrib.websites'): websites = domain.websites.all() @@ -107,7 +107,7 @@ class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin): display_websites.admin_order_field = 'websites__name' display_websites.short_description = _("Websites") display_websites.allow_tags = True - + def display_addresses(self, domain): if apps.isinstalled('orchestra.contrib.mailboxes'): add_url = reverse('admin:mailboxes_address_add') @@ -127,7 +127,7 @@ class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin): display_addresses.short_description = _("Addresses") display_addresses.admin_order_field = 'addresses__count' display_addresses.allow_tags = True - + def implicit_records(self, domain): defaults = [] types = set(domain.records.values_list('type', flat=True)) @@ -149,7 +149,7 @@ class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin): return '
'.join(lines) implicit_records.short_description = _("Implicit records") implicit_records.allow_tags = True - + def get_fieldsets(self, request, obj=None): """ Add SOA fields when domain is top """ fieldsets = super(DomainAdmin, self).get_fieldsets(request, obj) @@ -175,13 +175,13 @@ class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin): if 'top_link' not in existing: fieldsets[0][1]['fields'].insert(2, 'top_link') return fieldsets - + def get_inline_instances(self, request, obj=None): inlines = super(DomainAdmin, self).get_inline_instances(request, obj) if not obj or not obj.is_top: return [inline for inline in inlines if type(inline) != DomainInline] return inlines - + def get_queryset(self, request): """ Order by structured name and imporve performance """ qs = super(DomainAdmin, self).get_queryset(request) @@ -196,7 +196,7 @@ class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin): if apps.isinstalled('orchestra.contrib.mailboxes'): qs = qs.annotate(models.Count('addresses')) return qs - + def save_model(self, request, obj, form, change): """ batch domain creation support """ super(DomainAdmin, self).save_model(request, obj, form, change) @@ -205,7 +205,7 @@ class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin): for name in form.extra_names: domain = Domain.objects.create(name=name, account_id=obj.account_id) self.extra_domains.append(domain) - + def save_related(self, request, form, formsets, change): """ batch domain creation support """ super(DomainAdmin, self).save_related(request, form, formsets, change) diff --git a/orchestra/contrib/domains/tests/functional_tests/tests.py b/orchestra/contrib/domains/tests/functional_tests/tests.py index fbc92478..f13342e4 100644 --- a/orchestra/contrib/domains/tests/functional_tests/tests.py +++ b/orchestra/contrib/domains/tests/functional_tests/tests.py @@ -4,7 +4,7 @@ import socket from functools import partial from django.conf import settings as djsettings -from django.core.urlresolvers import reverse +from django.urls import reverse from selenium.webdriver.support.select import Select from orchestra.contrib.orchestration.models import Server, Route @@ -23,7 +23,7 @@ class DomainTestMixin(object): SLAVE_SERVER = os.environ.get('ORCHESTRA_SLAVE_SERVER', 'localhost') MASTER_SERVER_ADDR = socket.gethostbyname(MASTER_SERVER) SLAVE_SERVER_ADDR = socket.gethostbyname(SLAVE_SERVER) - + def setUp(self): djsettings.DEBUG = True super(DomainTestMixin, self).setUp() @@ -53,19 +53,19 @@ class DomainTestMixin(object): (Record.CNAME, 'external.server.org.'), ) self.django_domain_name = 'django%s.lan' % random_ascii(10) - + def add_route(self): raise NotImplementedError - + def add(self, domain_name, records): raise NotImplementedError - + def delete(self, domain_name, records): raise NotImplementedError - + def update(self, domain_name, records): raise NotImplementedError - + def validate_add(self, server_addr, domain_name): context = { 'domain_name': domain_name, @@ -81,7 +81,7 @@ class DomainTestMixin(object): self.assertEqual('%s.' % settings.DOMAINS_DEFAULT_NAME_SERVER, soa[4]) hostmaster = utils.format_hostmaster(settings.DOMAINS_DEFAULT_HOSTMASTER) self.assertEqual(hostmaster, soa[5]) - + dig_ns = 'dig @%(server_addr)s %(domain_name)s NS|grep "\sNS\s"' name_servers = run(dig_ns % context).stdout # testdomain.org. 3600 IN NS ns1.orchestra.lan. @@ -95,7 +95,7 @@ class DomainTestMixin(object): self.assertEqual('IN', ns[2]) self.assertEqual('NS', ns[3]) self.assertIn(ns[4], ns_records) - + dig_mx = 'dig @%(server_addr)s %(domain_name)s MX|grep "\sMX\s"' mail_servers = run(dig_mx % context).stdout for mx in mail_servers.splitlines(): @@ -107,7 +107,7 @@ class DomainTestMixin(object): self.assertEqual('MX', mx[3]) self.assertIn(mx[4], ['10', '20']) self.assertIn(mx[5], ['mail2.orchestra.lan.', 'mail.orchestra.lan.']) - + def validate_delete(self, server_addr, domain_name): context = { 'domain_name': domain_name, @@ -122,7 +122,7 @@ class DomainTestMixin(object): self.assertNotEqual('%s.' % settings.DOMAINS_DEFAULT_NAME_SERVER, soa[4]) hostmaster = utils.format_hostmaster(settings.DOMAINS_DEFAULT_HOSTMASTER) self.assertNotEqual(hostmaster, soa[5]) - + def validate_update(self, server_addr, domain_name): context = { 'domain_name': domain_name, @@ -138,7 +138,7 @@ class DomainTestMixin(object): self.assertEqual('%s.' % settings.DOMAINS_DEFAULT_NAME_SERVER, soa[4]) hostmaster = utils.format_hostmaster(settings.DOMAINS_DEFAULT_HOSTMASTER) self.assertEqual(hostmaster, soa[5]) - + dig_ns = 'dig @%(server_addr)s %(domain_name)s NS |grep "\sNS\s"' name_servers = run(dig_ns % context).stdout ns_records = ['ns1.%s.' % self.domain_name, 'ns2.%s.' % self.domain_name] @@ -151,7 +151,7 @@ class DomainTestMixin(object): self.assertEqual('IN', ns[2]) self.assertEqual('NS', ns[3]) self.assertIn(ns[4], ns_records) - + dig_mx = 'dig @%(server_addr)s %(domain_name)s MX | grep "\sMX\s"' mx = run(dig_mx % context).stdout.split() # testdomain.org. 3600 IN MX 10 orchestra.lan. @@ -161,7 +161,7 @@ class DomainTestMixin(object): self.assertEqual('MX', mx[3]) self.assertIn(mx[4], ['30', '40']) self.assertIn(mx[5], ['mail3.orchestra.lan.', 'mail4.orchestra.lan.']) - + def validate_www_update(self, server_addr, domain_name): context = { 'domain_name': domain_name, @@ -175,7 +175,7 @@ class DomainTestMixin(object): self.assertEqual('IN', cname[2]) self.assertEqual('CNAME', cname[3]) self.assertEqual('external.server.org.', cname[4]) - + def test_add(self): self.add(self.ns1_name, self.ns1_records) self.add(self.ns2_name, self.ns2_records) @@ -184,7 +184,7 @@ class DomainTestMixin(object): self.validate_add(self.MASTER_SERVER_ADDR, self.domain_name) time.sleep(1) self.validate_add(self.SLAVE_SERVER_ADDR, self.domain_name) - + def test_delete(self): self.add(self.ns1_name, self.ns1_records) self.add(self.ns2_name, self.ns2_records) @@ -193,7 +193,7 @@ class DomainTestMixin(object): for name in [self.domain_name, self.ns1_name, self.ns2_name]: self.validate_delete(self.MASTER_SERVER_ADDR, name) self.validate_delete(self.SLAVE_SERVER_ADDR, name) - + def test_update(self): self.add(self.ns1_name, self.ns1_records) self.add(self.ns2_name, self.ns2_records) @@ -209,7 +209,7 @@ class DomainTestMixin(object): self.validate_www_update(self.MASTER_SERVER_ADDR, self.domain_name) time.sleep(5) self.validate_www_update(self.SLAVE_SERVER_ADDR, self.domain_name) - + def test_add_add_delete_delete(self): self.add(self.ns1_name, self.ns1_records) self.add(self.ns2_name, self.ns2_records) @@ -221,7 +221,7 @@ class DomainTestMixin(object): self.delete(self.django_domain_name) self.validate_delete(self.MASTER_SERVER_ADDR, self.django_domain_name) self.validate_delete(self.SLAVE_SERVER_ADDR, self.django_domain_name) - + def test_bad_creation(self): self.assertRaises((self.rest.ResponseStatusError, AssertionError), self.add, self.domain_name, self.domain_records) @@ -232,7 +232,7 @@ class AdminDomainMixin(DomainTestMixin): super(AdminDomainMixin, self).setUp() self.add_route() self.admin_login() - + def _add_records(self, records): self.selenium.find_element_by_link_text('Add another Record').click() for i, record in zip(range(0, len(records)), records): @@ -244,29 +244,29 @@ class AdminDomainMixin(DomainTestMixin): value_input.clear() value_input.send_keys(value) return value_input - + @snapshot_on_error def add(self, domain_name, records): add = reverse('admin:domains_domain_add') url = self.live_server_url + add self.selenium.get(url) - + name = self.selenium.find_element_by_id('id_name') name.send_keys(domain_name) - + account_input = self.selenium.find_element_by_id('id_account') account_select = Select(account_input) account_select.select_by_value(str(self.account.pk)) - + value_input = self._add_records(records) value_input.submit() self.assertNotEqual(url, self.selenium.current_url) - + @snapshot_on_error def delete(self, domain_name): domain = Domain.objects.get(name=domain_name) self.admin_delete(domain) - + @snapshot_on_error def update(self, domain_name, records): domain = Domain.objects.get(name=domain_name) @@ -283,18 +283,18 @@ class RESTDomainMixin(DomainTestMixin): super(RESTDomainMixin, self).setUp() self.rest_login() self.add_route() - + @save_response_on_error def add(self, domain_name, records): records = [ dict(type=type, value=value) for type,value in records ] self.rest.domains.create(name=domain_name, records=records) - + @save_response_on_error def delete(self, domain_name): domain = Domain.objects.get(name=domain_name) domain = self.rest.domains.retrieve(id=domain.pk) domain.delete() - + @save_response_on_error def update(self, domain_name, records): records = [ dict(type=type, value=value) for type,value in records ] @@ -307,7 +307,7 @@ class Bind9BackendMixin(object): DEPENDENCIES = ( 'orchestra.contrib.orchestration', ) - + def add_route(self): master = Server.objects.create(name=self.MASTER_SERVER, address=self.MASTER_SERVER_ADDR) backend = backends.Bind9MasterDomainController.get_name() diff --git a/orchestra/contrib/history/admin.py b/orchestra/contrib/history/admin.py index 09a35e07..ebd80e46 100644 --- a/orchestra/contrib/history/admin.py +++ b/orchestra/contrib/history/admin.py @@ -1,6 +1,6 @@ from django.contrib import admin from django.utils.translation import ugettext_lazy as _ -from django.core.urlresolvers import reverse, NoReverseMatch +from django.urls import reverse, NoReverseMatch from django.contrib.admin.templatetags.admin_urls import add_preserved_filters from django.http import HttpResponseRedirect from django.contrib.admin.utils import unquote @@ -30,10 +30,10 @@ class LogEntryAdmin(admin.ModelAdmin): actions = None list_select_related = ('user', 'content_type') list_display_links = None - + user_link = admin_link('user') display_action_time = admin_date('action_time', short_description=_("Time")) - + def display_message(self, log): edit = '' % { 'url': reverse('admin:admin_logentry_change', args=(log.pk,)), @@ -58,7 +58,7 @@ class LogEntryAdmin(admin.ModelAdmin): display_message.short_description = _("Message") display_message.admin_order_field = 'action_flag' display_message.allow_tags = True - + def display_action(self, log): if log.is_addition(): return _("Added") @@ -67,7 +67,7 @@ class LogEntryAdmin(admin.ModelAdmin): return _("Deleted") display_action.short_description = _("Action") display_action.admin_order_field = 'action_flag' - + def content_object_link(self, log): ct = log.content_type view = 'admin:%s_%s_change' % (ct.app_label, ct.model) @@ -79,7 +79,7 @@ class LogEntryAdmin(admin.ModelAdmin): content_object_link.short_description = _("Content object") content_object_link.admin_order_field = 'object_repr' content_object_link.allow_tags = True - + def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None): """ Add rel_opts and object to context """ if not add and 'edit' in request.GET.urlencode(): @@ -89,14 +89,14 @@ class LogEntryAdmin(admin.ModelAdmin): }) return super(LogEntryAdmin, self).render_change_form( request, context, add, change, form_url, obj) - + def response_change(self, request, obj): """ save and continue preserve edit query string """ response = super(LogEntryAdmin, self).response_change(request, obj) if 'edit' in request.GET.urlencode() and 'edit' not in response.url: return HttpResponseRedirect(response.url + '?edit=True') return response - + def response_post_save_change(self, request, obj): """ save redirect to object history """ if 'edit' in request.GET.urlencode(): @@ -109,19 +109,19 @@ class LogEntryAdmin(admin.ModelAdmin): }, post_url) return HttpResponseRedirect(post_url) return super(LogEntryAdmin, self).response_post_save_change(request, obj) - + def has_add_permission(self, *args, **kwargs): return False - + def has_delete_permission(self, *args, **kwargs): return False - + def log_addition(self, *args, **kwargs): pass - + def log_change(self, *args, **kwargs): pass - + def log_deletion(self, *args, **kwargs): pass diff --git a/orchestra/contrib/issues/admin.py b/orchestra/contrib/issues/admin.py index 27580708..5dcc32ac 100644 --- a/orchestra/contrib/issues/admin.py +++ b/orchestra/contrib/issues/admin.py @@ -1,7 +1,7 @@ from django import forms from django.conf.urls import url from django.contrib import admin -from django.core.urlresolvers import reverse +from django.urls import reverse from django.db import models from django.http import HttpResponse from django.shortcuts import get_object_or_404 @@ -21,14 +21,14 @@ from .helpers import get_ticket_changes, markdown_formated_changes, filter_actio from .models import Ticket, Queue, Message -PRIORITY_COLORS = { +PRIORITY_COLORS = { Ticket.HIGH: 'red', Ticket.MEDIUM: 'darkorange', Ticket.LOW: 'green', } -STATE_COLORS = { +STATE_COLORS = { Ticket.NEW: 'grey', Ticket.IN_PROGRESS: 'darkorange', Ticket.FEEDBACK: 'purple', @@ -44,12 +44,12 @@ class MessageReadOnlyInline(admin.TabularInline): can_delete = False fields = ('content_html',) readonly_fields = ('content_html',) - + class Media: css = { 'all': ('orchestra/css/hide-inline-id.css',) } - + def content_html(self, msg): context = { 'number': msg.number, @@ -64,10 +64,10 @@ class MessageReadOnlyInline(admin.TabularInline): return header + content content_html.short_description = _("Content") content_html.allow_tags = True - + def has_add_permission(self, request): return False - + def has_delete_permission(self, request, obj=None): return False @@ -79,12 +79,12 @@ class MessageInline(admin.TabularInline): form = MessageInlineForm can_delete = False fields = ('content',) - + def get_formset(self, request, obj=None, **kwargs): """ hook request.user on the inline form """ self.form.user = request.user return super(MessageInline, self).get_formset(request, obj, **kwargs) - + def get_queryset(self, request): """ Don't show any message """ qs = super(MessageInline, self).get_queryset(request) @@ -103,14 +103,14 @@ class TicketInline(admin.TabularInline): model = Ticket extra = 0 max_num = 0 - + creator_link = admin_link('creator') owner_link = admin_link('owner') created = admin_link('created_at') updated = admin_link('updated_at') colored_state = admin_colored('state', colors=STATE_COLORS, bold=False) colored_priority = admin_colored('priority', colors=PRIORITY_COLORS, bold=False) - + def ticket_id(self, instance): return '%s' % admin_link()(instance) ticket_id.short_description = '#' @@ -176,7 +176,7 @@ class TicketAdmin(ExtendedModelAdmin): }), ) list_select_related = ('queue', 'owner', 'creator') - + class Media: css = { 'all': ('issues/css/ticket-admin.css',) @@ -184,14 +184,14 @@ class TicketAdmin(ExtendedModelAdmin): js = ( 'issues/js/ticket-admin.js', ) - + display_creator = admin_link('creator') display_queue = admin_link('queue') display_owner = admin_link('owner') updated = admin_date('updated_at') display_state = admin_colored('state', colors=STATE_COLORS, bold=False) display_priority = admin_colored('priority', colors=PRIORITY_COLORS, bold=False) - + def display_summary(self, ticket): context = { 'creator': admin_link('creator')(self, ticket) if ticket.creator else ticket.creator_name, @@ -208,7 +208,7 @@ class TicketAdmin(ExtendedModelAdmin): return '

Added by %(creator)s about %(created)s%(updated)s

' % context display_summary.short_description = 'Summary' display_summary.allow_tags = True - + def unbold_id(self, ticket): """ Unbold id if ticket is read """ if ticket.is_read_by(self.user): @@ -217,7 +217,7 @@ class TicketAdmin(ExtendedModelAdmin): unbold_id.allow_tags = True unbold_id.short_description = "#" unbold_id.admin_order_field = 'id' - + def bold_subject(self, ticket): """ Bold subject when tickets are unread for request.user """ if ticket.is_read_by(self.user): @@ -226,31 +226,31 @@ class TicketAdmin(ExtendedModelAdmin): bold_subject.allow_tags = True bold_subject.short_description = _("Subject") bold_subject.admin_order_field = 'subject' - + def formfield_for_dbfield(self, db_field, **kwargs): """ Make value input widget bigger """ if db_field.name == 'subject': kwargs['widget'] = forms.TextInput(attrs={'size':'120'}) return super(TicketAdmin, self).formfield_for_dbfield(db_field, **kwargs) - + def save_model(self, request, obj, *args, **kwargs): """ Define creator for new tickets """ if not obj.pk: obj.creator = request.user super(TicketAdmin, self).save_model(request, obj, *args, **kwargs) obj.mark_as_read_by(request.user) - + def get_urls(self): """ add markdown preview url """ return [ url(r'^preview/$', wrap_admin_view(self, self.message_preview_view)) ] + super(TicketAdmin, self).get_urls() - + def add_view(self, request, form_url='', extra_context=None): """ Do not sow message inlines """ return super(TicketAdmin, self).add_view(request, form_url, extra_context) - + def change_view(self, request, object_id, form_url='', extra_context=None): """ Change view actions based on ticket state """ ticket = get_object_or_404(Ticket, pk=object_id) @@ -269,12 +269,12 @@ class TicketAdmin(ExtendedModelAdmin): context.update(extra_context or {}) return super(TicketAdmin, self).change_view(request, object_id, form_url=form_url, extra_context=context) - + def changelist_view(self, request, extra_context=None): # Hook user for bold_subject self.user = request.user return super(TicketAdmin,self).changelist_view(request, extra_context=extra_context) - + def message_preview_view(self, request): """ markdown preview render via ajax """ data = request.POST.get("data") @@ -287,12 +287,12 @@ class QueueAdmin(admin.ModelAdmin): actions = (set_default_queue,) inlines = (TicketInline,) ordering = ('name',) - + class Media: css = { 'all': ('orchestra/css/hide-inline-id.css',) } - + def num_tickets(self, queue): num = queue.tickets__count url = reverse('admin:issues_ticket_changelist') @@ -301,7 +301,7 @@ class QueueAdmin(admin.ModelAdmin): num_tickets.short_description = _("Tickets") num_tickets.admin_order_field = 'tickets__count' num_tickets.allow_tags = True - + def get_list_display(self, request): """ show notifications """ list_display = list(self.list_display) @@ -312,7 +312,7 @@ class QueueAdmin(admin.ModelAdmin): display_notify.boolean = True list_display.append(display_notify) return list_display - + def get_queryset(self, request): qs = super(QueueAdmin, self).get_queryset(request) qs = qs.annotate(models.Count('tickets')) diff --git a/orchestra/contrib/lists/tests/functional_tests/tests.py b/orchestra/contrib/lists/tests/functional_tests/tests.py index 8ba93abc..447a8249 100644 --- a/orchestra/contrib/lists/tests/functional_tests/tests.py +++ b/orchestra/contrib/lists/tests/functional_tests/tests.py @@ -7,7 +7,7 @@ from email.mime.text import MIMEText import requests from django.conf import settings as djsettings from django.core.management.base import CommandError -from django.core.urlresolvers import reverse +from django.urls import reverse from orchestra.admin.utils import change_url from orchestra.contrib.domains.models import Domain from orchestra.contrib.orchestration.models import Route, Server diff --git a/orchestra/contrib/mailboxes/admin.py b/orchestra/contrib/mailboxes/admin.py index d6965655..0336c052 100644 --- a/orchestra/contrib/mailboxes/admin.py +++ b/orchestra/contrib/mailboxes/admin.py @@ -3,7 +3,7 @@ from urllib.parse import parse_qs from django import forms from django.contrib import admin, messages -from django.core.urlresolvers import reverse +from django.urls import reverse from django.db.models import F, Count, Value as V from django.db.models.functions import Concat from django.utils.safestring import mark_safe @@ -28,7 +28,7 @@ from .widgets import OpenCustomFilteringOnSelect class AutoresponseInline(admin.StackedInline): model = Autoresponse verbose_name_plural = _("autoresponse") - + def formfield_for_dbfield(self, db_field, **kwargs): if db_field.name == 'subject': kwargs['widget'] = forms.TextInput(attrs={'size':'118'}) @@ -76,12 +76,12 @@ class MailboxAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedMo form = MailboxChangeForm list_prefetch_related = ('addresses__domain',) actions = (disable, enable, list_accounts) - + def __init__(self, *args, **kwargs): super(MailboxAdmin, self).__init__(*args, **kwargs) if settings.MAILBOXES_LOCAL_DOMAIN: type(self).actions = self.actions + (SendMailboxEmail(),) - + def display_addresses(self, mailbox): # Get from forwards cache = caches.get_request_cache() @@ -111,7 +111,7 @@ class MailboxAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedMo return '
'.join(addresses+forwards) display_addresses.short_description = _("Addresses") display_addresses.allow_tags = True - + def display_forwards(self, mailbox): forwards = [] for addr in mailbox.get_forwards(): @@ -120,19 +120,19 @@ class MailboxAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedMo return '
'.join(forwards) display_forwards.short_description = _("Forward from") display_forwards.allow_tags = True - + def display_filtering(self, mailbox): """ becacuse of allow_tags = True """ return mailbox.get_filtering_display() display_filtering.short_description = _("Filtering") display_filtering.admin_order_field = 'filtering' display_filtering.allow_tags = True - + def formfield_for_dbfield(self, db_field, **kwargs): if db_field.name == 'filtering': kwargs['widget'] = OpenCustomFilteringOnSelect() return super(MailboxAdmin, self).formfield_for_dbfield(db_field, **kwargs) - + def get_fieldsets(self, request, obj=None): fieldsets = super(MailboxAdmin, self).get_fieldsets(request, obj) if obj and obj.filtering == obj.CUSTOM: @@ -144,31 +144,31 @@ class MailboxAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedMo fieldsets = list(copy.deepcopy(fieldsets)) fieldsets.pop(-1) return fieldsets - + def get_form(self, *args, **kwargs): form = super(MailboxAdmin, self).get_form(*args, **kwargs) form.modeladmin = self return form - + def get_search_results(self, request, queryset, search_term): # Remove local domain from the search term if present (implicit local addreƧ) search_term = search_term.replace('@'+settings.MAILBOXES_LOCAL_DOMAIN, '') # Split address name from domain in order to support address searching search_term = search_term.replace('@', ' ') return super(MailboxAdmin, self).get_search_results(request, queryset, search_term) - + def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None): if not add: self.check_unrelated_address(request, obj) self.check_matching_address(request, obj) return super(MailboxAdmin, self).render_change_form( request, context, add, change, form_url, obj) - + def log_addition(self, request, object, *args, **kwargs): self.check_unrelated_address(request, object) self.check_matching_address(request, object) return super(MailboxAdmin, self).log_addition(request, object, *args, **kwargs) - + def check_matching_address(self, request, obj): local_domain = settings.MAILBOXES_LOCAL_DOMAIN if obj.name and local_domain: @@ -183,7 +183,7 @@ class MailboxAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedMo "selecting it makes sense.") % (obj, addr) if msg not in (m.message for m in messages.get_messages(request)): self.message_user(request, msg, level=messages.WARNING) - + def check_unrelated_address(self, request, obj): # Check if there exists an unrelated local Address for this mbox local_domain = settings.MAILBOXES_LOCAL_DOMAIN @@ -204,7 +204,7 @@ class MailboxAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedMo # Prevent duplication (add_view+continue) if msg not in (m.message for m in messages.get_messages(request)): self.message_user(request, msg, level=messages.WARNING) - + def save_model(self, request, obj, form, change): """ save hacky mailbox.addresses and local domain clashing """ if obj.filtering != obj.CUSTOM: @@ -237,20 +237,20 @@ class AddressAdmin(SelectAccountAdminMixin, ExtendedModelAdmin): filter_horizontal = ['mailboxes'] form = AddressForm list_prefetch_related = ('mailboxes', 'domain') - + domain_link = admin_link('domain', order='domain__name') - + def display_email(self, address): return address.computed_email display_email.short_description = _("Email") display_email.admin_order_field = 'computed_email' - + def email_link(self, address): link = self.domain_link(address) return "%s@%s" % (address.name, link) email_link.short_description = _("Email") email_link.allow_tags = True - + def display_mailboxes(self, address): boxes = [] for mailbox in address.mailboxes.all(): @@ -260,7 +260,7 @@ class AddressAdmin(SelectAccountAdminMixin, ExtendedModelAdmin): display_mailboxes.short_description = _("Mailboxes") display_mailboxes.allow_tags = True display_mailboxes.admin_order_field = 'mailboxes__count' - + def display_all_mailboxes(self, address): boxes = [] for mailbox in address.get_mailboxes(): @@ -269,7 +269,7 @@ class AddressAdmin(SelectAccountAdminMixin, ExtendedModelAdmin): return '
'.join(boxes) display_all_mailboxes.short_description = _("Mailboxes links") display_all_mailboxes.allow_tags = True - + def display_forward(self, address): forward_mailboxes = {m.name: m for m in address.get_forward_mailboxes()} values = [] @@ -283,12 +283,12 @@ class AddressAdmin(SelectAccountAdminMixin, ExtendedModelAdmin): display_forward.short_description = _("Forward") display_forward.allow_tags = True display_forward.admin_order_field = 'forward' - + def formfield_for_dbfield(self, db_field, **kwargs): if db_field.name == 'forward': kwargs['widget'] = forms.TextInput(attrs={'size':'118'}) return super(AddressAdmin, self).formfield_for_dbfield(db_field, **kwargs) - + def get_fields(self, request, obj=None): """ Remove mailboxes field when creating address from a popup i.e. from mailbox add form """ fields = super(AddressAdmin, self).get_fields(request, obj) @@ -297,22 +297,22 @@ class AddressAdmin(SelectAccountAdminMixin, ExtendedModelAdmin): fields = list(fields) fields.remove('mailboxes') return fields - + def get_queryset(self, request): qs = super(AddressAdmin, self).get_queryset(request) qs = qs.annotate(computed_email=Concat(F('name'), V('@'), F('domain__name'))) return qs.annotate(Count('mailboxes')) - + def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None): if not add: self.check_matching_mailbox(request, obj) return super(AddressAdmin, self).render_change_form( request, context, add, change, form_url, obj) - + def log_addition(self, request, object, *args, **kwargs): self.check_matching_mailbox(request, object) return super(AddressAdmin, self).log_addition(request, object, *args, **kwargs) - + def check_matching_mailbox(self, request, obj): # Check if new addresse matches with a mbox because of having a local domain if obj.name and obj.domain and obj.domain.name == settings.MAILBOXES_LOCAL_DOMAIN: diff --git a/orchestra/contrib/mailboxes/tests/functional_tests/tests.py b/orchestra/contrib/mailboxes/tests/functional_tests/tests.py index 66459968..6ae693bb 100644 --- a/orchestra/contrib/mailboxes/tests/functional_tests/tests.py +++ b/orchestra/contrib/mailboxes/tests/functional_tests/tests.py @@ -11,7 +11,7 @@ from django.apps import apps from django.conf import settings as djsettings from django.contrib.contenttypes.models import ContentType from django.core.management.base import CommandError -from django.core.urlresolvers import reverse +from django.urls import reverse from selenium.webdriver.support.select import Select from orchestra.contrib.orchestration.models import Server, Route diff --git a/orchestra/contrib/mailer/actions.py b/orchestra/contrib/mailer/actions.py index d4a50f58..1ba1b90a 100644 --- a/orchestra/contrib/mailer/actions.py +++ b/orchestra/contrib/mailer/actions.py @@ -1,4 +1,4 @@ -from django.core.urlresolvers import reverse +from django.urls import reverse from django.shortcuts import redirect diff --git a/orchestra/contrib/mailer/admin.py b/orchestra/contrib/mailer/admin.py index b979c9aa..1eaabad0 100644 --- a/orchestra/contrib/mailer/admin.py +++ b/orchestra/contrib/mailer/admin.py @@ -3,7 +3,7 @@ import email from django import forms from django.contrib import admin -from django.core.urlresolvers import reverse +from django.urls import reverse from django.db.models import Count from django.shortcuts import redirect from django.utils.translation import ugettext_lazy as _ @@ -52,11 +52,11 @@ class MessageAdmin(ExtendedModelAdmin): ) date_hierarchy = 'created_at' change_view_actions = (last,) - + colored_state = admin_colored('state', colors=COLORS) created_at_delta = admin_date('created_at') last_try_delta = admin_date('last_try') - + def display_subject(self, instance): subject = instance.subject if len(subject) > 64: @@ -65,7 +65,7 @@ class MessageAdmin(ExtendedModelAdmin): display_subject.short_description = _("Subject") display_subject.admin_order_field = 'subject' display_subject.allow_tags = True - + def display_retries(self, instance): num_logs = instance.logs__count if num_logs == 1: @@ -78,7 +78,7 @@ class MessageAdmin(ExtendedModelAdmin): display_retries.short_description = _("Retries") display_retries.admin_order_field = 'retries' display_retries.allow_tags = True - + def display_content(self, instance): part = email.message_from_string(instance.content) payload = part.get_payload() @@ -102,19 +102,19 @@ class MessageAdmin(ExtendedModelAdmin): return payload display_content.short_description = _("Content") display_content.allow_tags = True - + def display_full_subject(self, instance): return instance.subject display_full_subject.short_description = _("Subject") - + def display_from(self, instance): return instance.from_address display_from.short_description = _("From") - + def display_to(self, instance): return instance.to_address display_to.short_description = _("To") - + def get_urls(self): from django.conf.urls import url urls = super().get_urls() @@ -125,16 +125,16 @@ class MessageAdmin(ExtendedModelAdmin): name='%s_%s_send_pending' % info) ) return urls - + def get_queryset(self, request): qs = super().get_queryset(request) return qs.annotate(Count('logs')).defer('content') - + def send_pending_view(self, request): task(send_pending).apply_async() self.message_user(request, _("Pending messages are being sent on the background.")) return redirect('..') - + def formfield_for_dbfield(self, db_field, **kwargs): if db_field.name == 'subject': kwargs['widget'] = forms.TextInput(attrs={'size':'100'}) @@ -148,7 +148,7 @@ class SMTPLogAdmin(admin.ModelAdmin): list_filter = ('result',) fields = ('message_link', 'colored_result', 'date_delta', 'log_message') readonly_fields = fields - + message_link = admin_link('message') colored_result = admin_colored('result', colors=COLORS, bold=False) date_delta = admin_date('date') diff --git a/orchestra/contrib/miscellaneous/admin.py b/orchestra/contrib/miscellaneous/admin.py index a54b8be3..2f7d699c 100644 --- a/orchestra/contrib/miscellaneous/admin.py +++ b/orchestra/contrib/miscellaneous/admin.py @@ -1,6 +1,6 @@ from django import forms from django.contrib import admin -from django.core.urlresolvers import reverse +from django.urls import reverse from django.db import models from django.utils.safestring import mark_safe from django.utils.translation import ugettext_lazy as _ @@ -36,19 +36,19 @@ class MiscServiceAdmin(ExtendedModelAdmin): prepopulated_fields = {'name': ('verbose_name',)} change_readonly_fields = ('name',) actions = (disable, enable) - + def display_name(self, misc): return '%s' % (misc.description, misc.name) display_name.short_description = _("name") display_name.allow_tags = True display_name.admin_order_field = 'name' - + def display_verbose_name(self, misc): return '%s' % (misc.description, misc.verbose_name) display_verbose_name.short_description = _("verbose name") display_verbose_name.allow_tags = True display_verbose_name.admin_order_field = 'verbose_name' - + def num_instances(self, misc): """ return num slivers as a link to slivers changelist view """ num = misc.instances__count @@ -57,11 +57,11 @@ class MiscServiceAdmin(ExtendedModelAdmin): return mark_safe('{1}'.format(url, num)) num_instances.short_description = _("Instances") num_instances.admin_order_field = 'instances__count' - + def get_queryset(self, request): qs = super(MiscServiceAdmin, self).get_queryset(request) return qs.annotate(models.Count('instances', distinct=True)) - + def formfield_for_dbfield(self, db_field, **kwargs): """ Make value input widget bigger """ if db_field.name == 'description': @@ -83,21 +83,21 @@ class MiscellaneousAdmin(SelectPluginAdminMixin, AccountAdminMixin, ExtendedMode actions = (disable, enable) plugin_field = 'service' plugin = MiscServicePlugin - + service_link = admin_link('service') - + def dispaly_active(self, instance): return instance.active dispaly_active.short_description = _("Active") dispaly_active.boolean = True dispaly_active.admin_order_field = 'is_active' - + def get_service(self, obj): if obj is None: return self.plugin.get(self.plugin_value).related_instance else: return obj.service - + def get_fieldsets(self, request, obj=None): fieldsets = super().get_fieldsets(request, obj) fields = list(fieldsets[0][1]['fields']) @@ -110,7 +110,7 @@ class MiscellaneousAdmin(SelectPluginAdminMixin, AccountAdminMixin, ExtendedMode fields.insert(2, 'identifier') fieldsets[0][1]['fields'] = fields return fieldsets - + def get_form(self, request, obj=None, **kwargs): if obj: plugin = self.plugin.get(obj.service.name)() @@ -127,16 +127,16 @@ class MiscellaneousAdmin(SelectPluginAdminMixin, AccountAdminMixin, ExtendedMode validator = import_class(validator_path) validator(identifier) return identifier - + form.clean_identifier = clean_identifier return form - + def formfield_for_dbfield(self, db_field, **kwargs): """ Make value input widget bigger """ if db_field.name == 'description': kwargs['widget'] = forms.Textarea(attrs={'cols': 70, 'rows': 4}) return super(MiscellaneousAdmin, self).formfield_for_dbfield(db_field, **kwargs) - + def save_model(self, request, obj, form, change): if not change: plugin = self.plugin diff --git a/orchestra/contrib/orchestration/helpers.py b/orchestra/contrib/orchestration/helpers.py index 798164d0..768e9997 100644 --- a/orchestra/contrib/orchestration/helpers.py +++ b/orchestra/contrib/orchestration/helpers.py @@ -2,7 +2,7 @@ import textwrap from django.contrib import messages from django.core.mail import mail_admins -from django.core.urlresolvers import reverse, NoReverseMatch +from django.urls import reverse, NoReverseMatch from django.utils.html import escape from django.utils.safestring import mark_safe from django.utils.translation import ungettext, ugettext_lazy as _ diff --git a/orchestra/contrib/orchestration/middlewares.py b/orchestra/contrib/orchestration/middlewares.py index afab235e..2daefe19 100644 --- a/orchestra/contrib/orchestration/middlewares.py +++ b/orchestra/contrib/orchestration/middlewares.py @@ -1,7 +1,7 @@ from threading import local from django.contrib.admin.models import LogEntry -from django.core.urlresolvers import resolve +from django.urls import resolve from django.db import transaction from django.db.models.signals import pre_delete, post_save, m2m_changed from django.dispatch import receiver @@ -39,12 +39,12 @@ class OperationsMiddleware(object): """ Stores all the operations derived from save and delete signals and executes them at the end of the request/response cycle - + It also works as a transaction middleware, making requets to run within an atomic block. """ # Thread local is used because request object is not available on model signals thread_locals = local() - + @classmethod def get_pending_operations(cls): # Check if an error poped up before OperationsMiddleware.process_request() @@ -54,7 +54,7 @@ class OperationsMiddleware(object): request.pending_operations = OrderedSet() return request.pending_operations return set() - + @classmethod def get_route_cache(cls): """ chache the routes to save sql queries """ @@ -64,7 +64,7 @@ class OperationsMiddleware(object): request.route_cache = {} return request.route_cache return {} - + @classmethod def collect(cls, action, **kwargs): """ Collects all pending operations derived from model signals """ @@ -75,26 +75,26 @@ class OperationsMiddleware(object): kwargs['route_cache'] = cls.get_route_cache() instance = kwargs.pop('instance') manager.collect(instance, action, **kwargs) - + def enter_transaction_management(self): type(self).thread_locals.transaction = transaction.atomic() type(self).thread_locals.transaction.__enter__() - + def leave_transaction_management(self, exception=None): locals = type(self).thread_locals if hasattr(locals, 'transaction'): # Don't fucking know why sometimes thread_locals does not contain a transaction locals.transaction.__exit__(exception, None, None) - + def process_request(self, request): """ Store request on a thread local variable """ type(self).thread_locals.request = request self.enter_transaction_management() - + def process_exception(self, request, exception): """Rolls back the database and leaves transaction management""" self.leave_transaction_management(exception) - + def process_response(self, request, response): """ Processes pending backend operations """ if response.status_code != 500: diff --git a/orchestra/contrib/orders/actions.py b/orchestra/contrib/orders/actions.py index fbfb9369..5a91a3f7 100644 --- a/orchestra/contrib/orders/actions.py +++ b/orchestra/contrib/orders/actions.py @@ -1,5 +1,5 @@ from django.contrib import admin, messages -from django.core.urlresolvers import reverse +from django.urls import reverse from django.db import transaction from django.utils import timezone from django.utils.safestring import mark_safe @@ -17,7 +17,7 @@ class BillSelectedOrders(object): verbose_name = _("Bill") template = 'admin/orders/order/bill_selected_options.html' __name__ = 'bill_selected_orders' - + def __call__(self, modeladmin, request, queryset): """ make this monster behave like a function """ self.modeladmin = modeladmin @@ -34,7 +34,7 @@ class BillSelectedOrders(object): del(self.queryset) del(self.context) return ret - + def set_options(self, request): form = BillSelectedOptionsForm() if request.POST.get('step'): @@ -56,7 +56,7 @@ class BillSelectedOrders(object): 'form': form, }) return render(request, self.template, self.context) - + def select_related(self, request): # TODO use changelist ? related = self.queryset.get_related().select_related('account', 'service') @@ -76,7 +76,7 @@ class BillSelectedOrders(object): 'form': form, }) return render(request, self.template, self.context) - + @transaction.atomic def confirmation(self, request): form = BillSelectConfirmationForm(initial=self.options) diff --git a/orchestra/contrib/orders/admin.py b/orchestra/contrib/orders/admin.py index a2918f11..79076067 100644 --- a/orchestra/contrib/orders/admin.py +++ b/orchestra/contrib/orders/admin.py @@ -1,13 +1,13 @@ from django import forms from django.contrib import admin -from django.core.urlresolvers import reverse, NoReverseMatch +from django.urls import reverse, NoReverseMatch from django.db.models import Prefetch from django.utils import timezone from django.utils.html import escape from django.utils.safestring import mark_safe from django.utils.translation import ugettext_lazy as _ -from orchestra.admin import ExtendedModelAdmin +from orchestra.admin import ExtendedModelAdmin from orchestra.admin.utils import admin_link, admin_date, change_url from orchestra.contrib.accounts.actions import list_accounts from orchestra.contrib.accounts.admin import AccountAdminMixin @@ -22,10 +22,10 @@ class MetricStorageInline(admin.TabularInline): model = MetricStorage readonly_fields = ('value', 'created_on', 'updated_on') extra = 0 - + def has_add_permission(self, request, obj=None): return False - + def get_fieldsets(self, request, obj=None): if obj: url = reverse('admin:orders_metricstorage_changelist') @@ -33,7 +33,7 @@ class MetricStorageInline(admin.TabularInline): title = _('Metric storage, last 10 entries, (See all)') self.verbose_name_plural = mark_safe(title % url) return super(MetricStorageInline, self).get_fieldsets(request, obj) - + def get_queryset(self, request): qs = super(MetricStorageInline, self).get_queryset(request) change_view = bool(self.parent_object and self.parent_object.pk) @@ -106,17 +106,17 @@ class OrderAdmin(AccountAdminMixin, ExtendedModelAdmin): 'content_object_repr', 'content_object_link', 'bills_links', 'account_link', 'service_link' ) - + service_link = admin_link('service') display_registered_on = admin_date('registered_on') display_cancelled_on = admin_date('cancelled_on') - + def display_description(self, order): return order.description[:64] display_description.short_description = _("Description") display_description.allow_tags = True display_description.admin_order_field = 'description' - + def content_object_link(self, order): if order.content_object: try: @@ -131,7 +131,7 @@ class OrderAdmin(AccountAdminMixin, ExtendedModelAdmin): content_object_link.short_description = _("Content object") content_object_link.allow_tags = True content_object_link.admin_order_field = 'content_object_repr' - + def bills_links(self, order): bills = [] make_link = admin_link() @@ -140,7 +140,7 @@ class OrderAdmin(AccountAdminMixin, ExtendedModelAdmin): return '
'.join(bills) bills_links.short_description = _("Bills") bills_links.allow_tags = True - + def display_billed_until(self, order): billed_until = order.billed_until red = False @@ -163,7 +163,7 @@ class OrderAdmin(AccountAdminMixin, ExtendedModelAdmin): display_billed_until.short_description = _("billed until") display_billed_until.allow_tags = True display_billed_until.admin_order_field = 'billed_until' - + def display_metric(self, order): """ dispalys latest metric value, don't uses latest() because not loosing prefetch_related @@ -174,7 +174,7 @@ class OrderAdmin(AccountAdminMixin, ExtendedModelAdmin): return '' return metric.value display_metric.short_description = _("Metric") - + def formfield_for_dbfield(self, db_field, **kwargs): """ Make value input widget bigger """ if db_field.name == 'description': diff --git a/orchestra/contrib/payments/actions.py b/orchestra/contrib/payments/actions.py index 1a904c64..e6b4b348 100644 --- a/orchestra/contrib/payments/actions.py +++ b/orchestra/contrib/payments/actions.py @@ -2,7 +2,7 @@ from functools import partial from django.contrib import messages from django.contrib.admin import actions -from django.core.urlresolvers import reverse +from django.urls import reverse from django.db import transaction from django.shortcuts import render, redirect from django.utils.safestring import mark_safe diff --git a/orchestra/contrib/payments/admin.py b/orchestra/contrib/payments/admin.py index 37fe7c7d..f753231b 100644 --- a/orchestra/contrib/payments/admin.py +++ b/orchestra/contrib/payments/admin.py @@ -1,5 +1,5 @@ from django.contrib import admin -from django.core.urlresolvers import reverse +from django.urls import reverse from django.http import HttpResponseRedirect from django.utils.translation import ugettext_lazy as _ @@ -48,20 +48,20 @@ class TransactionInline(admin.TabularInline): 'amount', 'currency' ) readonly_fields = fields - + transaction_link = admin_link('__str__', short_description=_("ID")) bill_link = admin_link('bill') source_link = admin_link('source') display_state = admin_colored('state', colors=STATE_COLORS) - + class Media: css = { 'all': ('orchestra/css/hide-inline-id.css',) } - + def has_add_permission(self, *args, **kwargs): return False - + def get_queryset(self, *args, **kwargs): qs = super().get_queryset(*args, **kwargs) return qs.select_related('source', 'bill') @@ -116,28 +116,28 @@ class TransactionAdmin(SelectAccountAdminMixin, ExtendedModelAdmin): ) list_select_related = ('source', 'bill__account', 'process') date_hierarchy = 'created_at' - + bill_link = admin_link('bill') source_link = admin_link('source') process_link = admin_link('process', short_description=_("proc")) account_link = admin_link('bill__account') display_created_at = admin_date('created_at', short_description=_("Created")) display_modified_at = admin_date('modified_at', short_description=_("Modified")) - + def has_delete_permission(self, *args, **kwargs): return False - + def get_actions(self, request): actions = super().get_actions(request) if 'delete_selected' in actions: del actions['delete_selected'] return actions - + def get_change_readonly_fields(self, request, obj): if obj.state in (Transaction.WAITTING_PROCESSING, Transaction.WAITTING_EXECUTION): return () return ('amount', 'currency') - + def get_change_view_actions(self, obj=None): actions = super(TransactionAdmin, self).get_change_view_actions() exclude = [] @@ -153,7 +153,7 @@ class TransactionAdmin(SelectAccountAdminMixin, ExtendedModelAdmin): elif obj.state == Transaction.SECURED: return [] return [action for action in actions if action.__name__ not in exclude] - + def display_state(self, obj): state = admin_colored('state', colors=STATE_COLORS)(obj) help_text = obj.get_state_help() @@ -178,16 +178,16 @@ class TransactionProcessAdmin(ChangeViewActionsMixin, admin.ModelAdmin): actions.mark_process_as_executed, actions.abort, actions.commit, actions.report ) actions = change_view_actions + (actions.delete_selected,) - + display_state = admin_colored('state', colors=PROCESS_STATE_COLORS) display_created_at = admin_date('created_at', short_description=_("Created")) - + def file_url(self, process): if process.file: return '%s' % (process.file.url, process.file.name) file_url.allow_tags = True file_url.admin_order_field = 'file' - + def display_transactions(self, process): ids = [] lines = [] @@ -208,10 +208,10 @@ class TransactionProcessAdmin(ChangeViewActionsMixin, admin.ModelAdmin): return '%s' % (url, transactions) display_transactions.short_description = _("Transactions") display_transactions.allow_tags = True - + def has_add_permission(self, *args, **kwargs): return False - + def get_change_view_actions(self, obj=None): actions = super().get_change_view_actions() exclude = [] @@ -223,7 +223,7 @@ class TransactionProcessAdmin(ChangeViewActionsMixin, admin.ModelAdmin): elif obj.state == TransactionProcess.ABORTED: exclude = ['mark_process_as_executed', 'abort', 'commit'] return [action for action in actions if action.__name__ not in exclude] - + def delete_view(self, request, object_id, extra_context=None): queryset = self.model.objects.filter(id=object_id) related_transactions = helpers.pre_delete_processes(self, request, queryset) diff --git a/orchestra/contrib/plans/admin.py b/orchestra/contrib/plans/admin.py index 224865f2..c283d5e4 100644 --- a/orchestra/contrib/plans/admin.py +++ b/orchestra/contrib/plans/admin.py @@ -1,5 +1,5 @@ from django.contrib import admin -from django.core.urlresolvers import reverse +from django.urls import reverse from django.db import models from django.utils.translation import ugettext_lazy as _ @@ -28,7 +28,7 @@ class PlanAdmin(ExtendedModelAdmin): } change_readonly_fields = ('name',) inlines = [RateInline] - + def num_contracts(self, plan): num = plan.contracts__count url = reverse('admin:plans_contractedplan_changelist') @@ -37,7 +37,7 @@ class PlanAdmin(ExtendedModelAdmin): num_contracts.short_description = _("Contracts") num_contracts.admin_order_field = 'contracts__count' num_contracts.allow_tags = True - + def get_queryset(self, request): qs = super(PlanAdmin, self).get_queryset(request) return qs.annotate(models.Count('contracts', distinct=True)) @@ -49,7 +49,7 @@ class ContractedPlanAdmin(AccountAdminMixin, admin.ModelAdmin): list_select_related = ('plan', 'account') search_fields = ('account__username', 'plan__name', 'id') actions = (list_accounts,) - + plan_link = admin_link('plan') diff --git a/orchestra/contrib/resources/actions.py b/orchestra/contrib/resources/actions.py index ea1ec971..c355da2b 100644 --- a/orchestra/contrib/resources/actions.py +++ b/orchestra/contrib/resources/actions.py @@ -1,4 +1,4 @@ -from django.core.urlresolvers import reverse +from django.urls import reverse from django.shortcuts import redirect, render from django.utils.safestring import mark_safe from django.utils.translation import ungettext, ugettext_lazy as _ diff --git a/orchestra/contrib/resources/admin.py b/orchestra/contrib/resources/admin.py index fe3b0d05..462f717f 100644 --- a/orchestra/contrib/resources/admin.py +++ b/orchestra/contrib/resources/admin.py @@ -6,7 +6,7 @@ from django.contrib import admin, messages from django.contrib.contenttypes.admin import GenericTabularInline from django.contrib.contenttypes.forms import BaseGenericInlineFormSet from django.contrib.admin.utils import unquote -from django.core.urlresolvers import reverse +from django.urls import reverse from django.db.models import Q from django.shortcuts import redirect from django.templatetags.static import static @@ -58,7 +58,7 @@ class ResourceAdmin(ExtendedModelAdmin): 'name': ('verbose_name',) } list_select_related = ('content_type', 'crontab',) - + def change_view(self, request, object_id, form_url='', extra_context=None): """ Remaind user when monitor routes are not configured """ if request.method == 'GET': @@ -78,7 +78,7 @@ class ResourceAdmin(ExtendedModelAdmin): }) return super(ResourceAdmin, self).change_view(request, object_id, form_url=form_url, extra_context=extra_context) - + def save_model(self, request, obj, form, change): super(ResourceAdmin, self).save_model(request, obj, form, change) # best-effort @@ -93,7 +93,7 @@ class ResourceAdmin(ExtendedModelAdmin): modeladmin.inlines = inlines # reload Not always work sys.touch_wsgi() - + def formfield_for_dbfield(self, db_field, **kwargs): """ filter service content_types """ if db_field.name == 'content_type': @@ -127,10 +127,10 @@ class ResourceDataAdmin(ExtendedModelAdmin): change_view_actions = actions ordering = ('-updated_at',) list_select_related = ('resource__content_type', 'content_type') - + resource_link = admin_link('resource') display_updated = admin_date('updated_at', short_description=_("Updated")) - + def get_urls(self): """Returns the additional urls for the change view links""" urls = super(ResourceDataAdmin, self).get_urls() @@ -150,7 +150,7 @@ class ResourceDataAdmin(ExtendedModelAdmin): name='%s_%s_list_related' % (opts.app_label, opts.model_name) ), ] + urls - + def display_used(self, rdata): if rdata.used is None: return '' @@ -159,15 +159,15 @@ class ResourceDataAdmin(ExtendedModelAdmin): display_used.short_description = _("Used") display_used.admin_order_field = 'used' display_used.allow_tags = True - + def has_add_permission(self, *args, **kwargs): return False - + def used_monitordata_view(self, request, object_id): url = reverse('admin:resources_monitordata_changelist') url += '?resource_data=%s' % object_id return redirect(url) - + def list_related_view(self, request, app_name, model_name, object_id): resources = Resource.objects.select_related('content_type') resource_models = {r.content_type.model_class(): r.content_type_id for r in resources} @@ -203,9 +203,9 @@ class MonitorDataAdmin(ExtendedModelAdmin): list_select_related = ('content_type',) search_fields = ('content_object_repr',) date_hierarchy = 'created_at' - + display_created = admin_date('created_at', short_description=_("Created")) - + def filter_used_monitordata(self, request, queryset): query_string = parse_qs(request.META['QUERY_STRING']) resource_data = query_string.get('resource_data') @@ -221,7 +221,7 @@ class MonitorDataAdmin(ExtendedModelAdmin): ids += dataset.values_list('id', flat=True) return queryset.filter(id__in=ids) return queryset - + def get_queryset(self, request): queryset = super(MonitorDataAdmin, self).get_queryset(request) queryset = self.filter_used_monitordata(request, queryset) @@ -239,13 +239,13 @@ def resource_inline_factory(resources): class ResourceInlineFormSet(BaseGenericInlineFormSet): def total_form_count(self, resources=resources): return len(resources) - + @cached def get_queryset(self): """ Filter disabled resources """ queryset = super(ResourceInlineFormSet, self).get_queryset() return queryset.filter(resource__is_active=True).select_related('resource') - + @cached_property def forms(self, resources=resources): forms = [] @@ -276,7 +276,7 @@ def resource_inline_factory(resources): for i, resource in enumerate(resources_copy, len(queryset)): forms.append(self._construct_form(i, resource=resource)) return forms - + class ResourceInline(GenericTabularInline): model = ResourceData verbose_name_plural = _("resources") @@ -287,14 +287,14 @@ def resource_inline_factory(resources): 'verbose_name', 'display_used', 'display_updated', 'allocated', 'unit', ) readonly_fields = ('display_used', 'display_updated',) - + class Media: css = { 'all': ('orchestra/css/hide-inline-id.css',) } - + display_updated = admin_date('updated_at', default=_("Never")) - + def get_fieldsets(self, request, obj=None): if obj: opts = self.parent_model._meta @@ -303,7 +303,7 @@ def resource_inline_factory(resources): link = '%s' % (url, _("List related")) self.verbose_name_plural = mark_safe(_("Resources") + ' ' + link) return super(ResourceInline, self).get_fieldsets(request, obj) - + def display_used(self, rdata): update = '' history = '' @@ -330,11 +330,11 @@ def resource_inline_factory(resources): return _("No monitor") display_used.short_description = _("Used") display_used.allow_tags = True - + def has_add_permission(self, *args, **kwargs): """ Hidde add another """ return False - + return ResourceInline diff --git a/orchestra/contrib/saas/services/phplist.py b/orchestra/contrib/saas/services/phplist.py index 7b265b18..7b803f04 100644 --- a/orchestra/contrib/saas/services/phplist.py +++ b/orchestra/contrib/saas/services/phplist.py @@ -1,7 +1,7 @@ from django import forms from django.core import validators from django.core.exceptions import ValidationError -from django.core.urlresolvers import reverse +from django.urls import reverse from django.db.models import Q from django.utils.safestring import mark_safe from django.utils.translation import ugettext_lazy as _ @@ -25,7 +25,7 @@ class PHPListForm(SaaSPasswordForm): help_text=_("Dedicated mailbox used for reciving bounces."), widget=SpanWidget(display=settings.SAAS_PHPLIST_BOUNCES_MAILBOX_NAME.replace( '%(', '<').replace(')s', '>'))) - + def __init__(self, *args, **kwargs): super(PHPListForm, self).__init__(*args, **kwargs) self.fields['name'].label = _("Site name") @@ -76,14 +76,14 @@ class PHPListService(DBSoftwareService): allow_custom_url = settings.SAAS_PHPLIST_ALLOW_CUSTOM_URL db_name = settings.SAAS_PHPLIST_DB_NAME db_user = settings.SAAS_PHPLIST_DB_USER - + def get_mailbox_name(self): context = { 'name': self.instance.name, 'site_name': self.instance.name, } return settings.SAAS_PHPLIST_BOUNCES_MAILBOX_NAME % context - + def validate(self): super(PHPListService, self).validate() create = not self.instance.pk @@ -97,7 +97,7 @@ class PHPListService(DBSoftwareService): raise ValidationError({ 'name': e.messages, }) - + def save(self): super(PHPListService, self).save() account = self.get_account() @@ -111,7 +111,7 @@ class PHPListService(DBSoftwareService): 'mailbox_id': mailbox.pk, 'mailbox_name': mailbox_name, }) - + def delete(self): super(PHPListService, self).save() account = self.get_account() diff --git a/orchestra/contrib/services/actions.py b/orchestra/contrib/services/actions.py index b11b9b49..96d38e3d 100644 --- a/orchestra/contrib/services/actions.py +++ b/orchestra/contrib/services/actions.py @@ -1,5 +1,5 @@ from django.contrib.admin import helpers -from django.core.urlresolvers import reverse +from django.urls import reverse from django.db import transaction from django.shortcuts import render, redirect from django.template.response import TemplateResponse diff --git a/orchestra/contrib/services/admin.py b/orchestra/contrib/services/admin.py index 3d0f05a0..e8b823aa 100644 --- a/orchestra/contrib/services/admin.py +++ b/orchestra/contrib/services/admin.py @@ -1,7 +1,7 @@ from django import forms from django.conf.urls import url from django.contrib import admin -from django.core.urlresolvers import reverse +from django.urls import reverse from django.template.response import TemplateResponse from django.utils import timezone from django.utils.translation import ugettext_lazy as _ @@ -42,7 +42,7 @@ class ServiceAdmin(ChangeViewActionsMixin, admin.ModelAdmin): actions = (update_orders, clone, disable, enable) change_view_actions = actions + (view_help,) change_form_template = 'admin/services/service/change_form.html' - + def get_urls(self): """Returns the additional urls for the change view links""" urls = super(ServiceAdmin, self).get_urls() @@ -54,7 +54,7 @@ class ServiceAdmin(ChangeViewActionsMixin, admin.ModelAdmin): name='%s_%s_help' % (opts.app_label, opts.model_name) ) ] + urls - + def formfield_for_dbfield(self, db_field, **kwargs): """ Improve performance of account field and filter by account """ if db_field.name == 'content_type': @@ -64,7 +64,7 @@ class ServiceAdmin(ChangeViewActionsMixin, admin.ModelAdmin): if db_field.name in ['match', 'metric', 'order_description']: kwargs['widget'] = forms.TextInput(attrs={'size':'160'}) return super(ServiceAdmin, self).formfield_for_dbfield(db_field, **kwargs) - + def num_orders(self, service): num = service.orders__count url = reverse('admin:orders_order_changelist') @@ -73,7 +73,7 @@ class ServiceAdmin(ChangeViewActionsMixin, admin.ModelAdmin): num_orders.short_description = _("Orders") num_orders.admin_order_field = 'orders__count' num_orders.allow_tags = True - + def get_queryset(self, request): qs = super(ServiceAdmin, self).get_queryset(request) # Count active orders @@ -88,7 +88,7 @@ class ServiceAdmin(ChangeViewActionsMixin, admin.ModelAdmin): ) }) return qs - + def help_view(self, request, *args): opts = self.model._meta context = { diff --git a/orchestra/contrib/systemusers/tests/functional_tests/tests.py b/orchestra/contrib/systemusers/tests/functional_tests/tests.py index 96c38c37..9d3cf2e0 100644 --- a/orchestra/contrib/systemusers/tests/functional_tests/tests.py +++ b/orchestra/contrib/systemusers/tests/functional_tests/tests.py @@ -8,7 +8,7 @@ from functools import partial import paramiko from django.conf import settings as djsettings from django.core.management.base import CommandError -from django.core.urlresolvers import reverse +from django.urls import reverse from selenium.webdriver.support.select import Select from orchestra.admin.utils import change_url diff --git a/orchestra/contrib/webapps/admin.py b/orchestra/contrib/webapps/admin.py index 0297ae8b..9d93ee6a 100644 --- a/orchestra/contrib/webapps/admin.py +++ b/orchestra/contrib/webapps/admin.py @@ -1,6 +1,6 @@ from django import forms from django.contrib import admin -from django.core.urlresolvers import reverse +from django.urls import reverse from django.utils.encoding import force_text from django.utils.translation import ugettext, ugettext_lazy as _ @@ -21,16 +21,16 @@ from .types import AppType class WebAppOptionInline(admin.TabularInline): model = WebAppOption extra = 1 - + OPTIONS_HELP_TEXT = { op.name: force_text(op.help_text) for op in AppOption.get_plugins() } - + class Media: css = { 'all': ('orchestra/css/hide-inline-id.css',) } - + def formfield_for_dbfield(self, db_field, **kwargs): if db_field.name == 'value': kwargs['widget'] = forms.TextInput(attrs={'size':'100'}) @@ -63,9 +63,9 @@ class WebAppAdmin(SelectPluginAdminMixin, AccountAdminMixin, ExtendedModelAdmin) plugin_field = 'type' plugin_title = _("Web application type") actions = (list_accounts,) - + display_type = display_plugin_field('type') - + def display_websites(self, webapp): websites = [] for content in webapp.content_set.all(): @@ -83,7 +83,7 @@ class WebAppAdmin(SelectPluginAdminMixin, AccountAdminMixin, ExtendedModelAdmin) return '
'.join(websites) display_websites.short_description = _("web sites") display_websites.allow_tags = True - + def display_detail(self, webapp): try: return webapp.type_instance.get_detail() @@ -91,11 +91,11 @@ class WebAppAdmin(SelectPluginAdminMixin, AccountAdminMixin, ExtendedModelAdmin) return "Not available" display_detail.short_description = _("detail") display_detail.allow_tags = True - + # def get_form(self, request, obj=None, **kwargs): # form = super(WebAppAdmin, self).get_form(request, obj, **kwargs) # if obj: -# +# # def formfield_for_dbfield(self, db_field, **kwargs): # """ Make value input widget bigger """ diff --git a/orchestra/contrib/webapps/types/cms.py b/orchestra/contrib/webapps/types/cms.py index 80822cc2..0343ce15 100644 --- a/orchestra/contrib/webapps/types/cms.py +++ b/orchestra/contrib/webapps/types/cms.py @@ -1,6 +1,6 @@ from django import forms from django.core.exceptions import ValidationError -from django.core.urlresolvers import reverse +from django.urls import reverse from django.utils.safestring import mark_safe from django.utils.translation import ugettext_lazy as _ from rest_framework import serializers @@ -20,7 +20,7 @@ class CMSAppForm(PHPAppForm): password = forms.CharField(label=_("Password"), help_text=_("Initial database and WordPress admin password.
" "Subsequent changes to the admin password will not be reflected.")) - + def __init__(self, *args, **kwargs): super(CMSAppForm, self).__init__(*args, **kwargs) if self.instance: @@ -55,20 +55,20 @@ class CMSApp(PHPApp): db_type = Database.MYSQL abstract = True db_prefix = 'cms_' - + def get_db_name(self): db_name = '%s%s_%s' % (self.db_prefix, self.instance.name, self.instance.account) # Limit for mysql database names return db_name[:65] - + def get_db_user(self): db_name = self.get_db_name() # Limit for mysql user names return db_name[:16] - + def get_password(self): return random_ascii(10) - + def validate(self): super(CMSApp, self).validate() create = not self.instance.pk @@ -83,7 +83,7 @@ class CMSApp(PHPApp): raise ValidationError({ 'name': e.messages, }) - + def save(self): db_name = self.get_db_name() db_user = self.get_db_user() diff --git a/orchestra/contrib/websites/admin.py b/orchestra/contrib/websites/admin.py index e447683a..fc54b4bc 100644 --- a/orchestra/contrib/websites/admin.py +++ b/orchestra/contrib/websites/admin.py @@ -1,6 +1,6 @@ from django import forms from django.contrib import admin -from django.core.urlresolvers import resolve +from django.urls import resolve from django.db.models import Q from django.utils.encoding import force_text from django.utils.translation import ugettext_lazy as _ @@ -24,11 +24,11 @@ class WebsiteDirectiveInline(admin.TabularInline): model = WebsiteDirective formset = WebsiteDirectiveInlineFormSet extra = 1 - + DIRECTIVES_HELP_TEXT = { op.name: force_text(op.help_text) for op in SiteDirective.get_plugins() } - + def formfield_for_dbfield(self, db_field, **kwargs): if db_field.name == 'value': kwargs['widget'] = forms.TextInput(attrs={'size':'100'}) @@ -45,10 +45,10 @@ class ContentInline(AccountAdminMixin, admin.TabularInline): fields = ('webapp', 'webapp_link', 'webapp_type', 'path') readonly_fields = ('webapp_link', 'webapp_type') filter_by_account_fields = ['webapp'] - + webapp_link = admin_link('webapp', popup=True) webapp_link.short_description = _("Web App") - + def webapp_type(self, content): if not content.pk: return '' @@ -77,7 +77,7 @@ class WebsiteAdmin(SelectAccountAdminMixin, ExtendedModelAdmin): list_prefetch_related = ('domains', 'content_set__webapp') search_fields = ('name', 'account__username', 'domains__name', 'content__webapp__name') actions = (disable, enable, list_accounts) - + def display_domains(self, website): domains = [] for domain in website.domains.all(): @@ -87,7 +87,7 @@ class WebsiteAdmin(SelectAccountAdminMixin, ExtendedModelAdmin): display_domains.short_description = _("domains") display_domains.allow_tags = True display_domains.admin_order_field = 'domains' - + def display_webapps(self, website): webapps = [] for content in website.content_set.all(): @@ -104,7 +104,7 @@ class WebsiteAdmin(SelectAccountAdminMixin, ExtendedModelAdmin): return '
'.join(webapps) display_webapps.allow_tags = True display_webapps.short_description = _("Web apps") - + def formfield_for_dbfield(self, db_field, **kwargs): """ Exclude domains with exhausted ports @@ -124,7 +124,7 @@ class WebsiteAdmin(SelectAccountAdminMixin, ExtendedModelAdmin): qset = Q(qset & ~Q(websites__pk=object_id)) formfield.queryset = formfield.queryset.exclude(qset) return formfield - + def _create_formsets(self, request, obj, change): """ bind contents formset to directive formset for unique location cross-validation """ formsets, inline_instances = super(WebsiteAdmin, self)._create_formsets(request, obj, change) diff --git a/orchestra/models/fields.py b/orchestra/models/fields.py index 44331180..81ab5796 100644 --- a/orchestra/models/fields.py +++ b/orchestra/models/fields.py @@ -1,7 +1,7 @@ import os from django.core import exceptions -from django.core.urlresolvers import reverse +from django.urls import reverse from django.db import models from django.db.models.fields.files import FileField, FieldFile from django.utils.text import capfirst @@ -21,34 +21,34 @@ class MultiSelectField(models.CharField): defaults['initial'] = self.get_default() defaults.update(kwargs) return MultiSelectFormField(**defaults) - + def get_db_prep_value(self, value, connection=None, prepared=False): if isinstance(value, str): return value else: return ','.join(value) - + def to_python(self, value): if value: if isinstance(value, str): return value.split(',') return value return [] - + def from_db_value(self, value, expression, connection, context): if value: if isinstance(value, str): return value.split(',') return value return [] - + def contribute_to_class(self, cls, name): super(MultiSelectField, self).contribute_to_class(cls, name) if self.choices: def func(self, field=name, choices=dict(self.choices)): return ','.join([choices.get(value, value) for value in getattr(self, field)]) setattr(cls, 'get_%s_display' % self.name, func) - + def validate(self, value, model_instance): if self.choices: arr_choices = self.get_choices_selected(self.get_choices()) @@ -56,7 +56,7 @@ class MultiSelectField(models.CharField): if (opt_select not in arr_choices): msg = self.error_messages['invalid_choice'] % {'value': opt_select} raise exceptions.ValidationError(msg) - + def get_choices_selected(self, arr_choices=''): if not arr_choices: return False @@ -79,11 +79,11 @@ class PrivateFieldFile(FieldFile): filename = os.path.basename(self.path) args = [app_label, model_name, field_name, pk, filename] return reverse('private-media', args=args) - + @property def condition(self): return self.field.condition - + @property def attachment(self): return self.field.attachment @@ -91,7 +91,7 @@ class PrivateFieldFile(FieldFile): class PrivateFileField(FileField): attr_class = PrivateFieldFile - + def __init__(self, verbose_name=None, name=None, upload_to='', storage=None, attachment=True, condition=lambda request, instance: request.user.is_superuser, **kwargs): super(PrivateFileField, self).__init__(verbose_name, name, upload_to, storage, **kwargs) diff --git a/orchestra/permissions/api.py b/orchestra/permissions/api.py index abfcdb99..7f8dc251 100644 --- a/orchestra/permissions/api.py +++ b/orchestra/permissions/api.py @@ -1,16 +1,16 @@ -from django.core.urlresolvers import resolve +from django.urls import resolve from rest_framework.permissions import DjangoModelPermissions class OrchestraPermissionBackend(DjangoModelPermissions): """ Permissions according to each user """ - + def has_permission(self, request, view): queryset = getattr(view, 'queryset', None) if queryset is None: name = resolve(request.path).url_name return name == 'api-root' - + model_cls = queryset.model perms = self.get_required_permissions(request.method, model_cls) if (request.user and @@ -18,7 +18,7 @@ class OrchestraPermissionBackend(DjangoModelPermissions): request.user.has_perms(perms, model_cls)): return True return False - + def has_object_permission(self, request, view, obj): perms = self.get_required_permissions(request.method, type(obj)) if (request.user and diff --git a/orchestra/templatetags/utils.py b/orchestra/templatetags/utils.py index 9a88fd32..cadde7f9 100644 --- a/orchestra/templatetags/utils.py +++ b/orchestra/templatetags/utils.py @@ -4,7 +4,7 @@ import re from django import template from django.contrib.contenttypes.models import ContentType -from django.core.urlresolvers import reverse, NoReverseMatch +from django.urls import reverse, NoReverseMatch from django.forms import CheckboxInput from django.template.base import Node from django.template.defaultfilters import date @@ -54,7 +54,7 @@ def rest_to_admin_url(context): class OneLinerNode(Node): def __init__(self, nodelist): self.nodelist = nodelist - + def render(self, context): line = self.nodelist.render(context).replace('\n', ' ') return re.sub(r'\s\s+', '', line) diff --git a/orchestra/utils/tests.py b/orchestra/utils/tests.py index 31a5e1e3..ae37bd6f 100644 --- a/orchestra/utils/tests.py +++ b/orchestra/utils/tests.py @@ -5,7 +5,7 @@ from functools import wraps from django.conf import settings from django.contrib.auth import BACKEND_SESSION_KEY, SESSION_KEY from django.contrib.sessions.backends.db import SessionStore -from django.core.urlresolvers import reverse +from django.urls import reverse from django.test import LiveServerTestCase, TestCase from selenium.webdriver.firefox.webdriver import WebDriver from xvfbwrapper import Xvfb