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 '' % 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-', '
'.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 '