Merge pull request #8 from ribaguifi/dev/django2.1-admin
Refactor admin code to support Django 2.1
This commit is contained in:
commit
7b59931bcf
|
@ -5,7 +5,7 @@ from django import forms
|
||||||
from django.contrib.admin import helpers
|
from django.contrib.admin import helpers
|
||||||
from django.core import validators
|
from django.core import validators
|
||||||
from django.forms.models import modelformset_factory, BaseModelFormSet
|
from django.forms.models import modelformset_factory, BaseModelFormSet
|
||||||
from django.template import Template, Context
|
from django.template import Template
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from orchestra.forms.widgets import SpanWidget
|
from orchestra.forms.widgets import SpanWidget
|
||||||
|
@ -28,9 +28,9 @@ class AdminFormMixin(object):
|
||||||
' {% include "admin/includes/fieldset.html" %}'
|
' {% include "admin/includes/fieldset.html" %}'
|
||||||
'{% endfor %}'
|
'{% endfor %}'
|
||||||
)
|
)
|
||||||
context = Context({
|
context = {
|
||||||
'adminform': adminform
|
'adminform': adminform
|
||||||
})
|
}
|
||||||
return template.render(context)
|
return template.render(context)
|
||||||
|
|
||||||
|
|
||||||
|
@ -71,9 +71,9 @@ class AdminFormSet(BaseModelFormSet):
|
||||||
</div>
|
</div>
|
||||||
</div>""")
|
</div>""")
|
||||||
)
|
)
|
||||||
context = Context({
|
context = {
|
||||||
'formset': self
|
'formset': self
|
||||||
})
|
}
|
||||||
return template.render(context)
|
return template.render(context)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ from django.urls import reverse, NoReverseMatch
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.shortcuts import redirect
|
from django.shortcuts import redirect
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.html import escape
|
from django.utils.html import escape, format_html
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
|
|
||||||
from orchestra.models.utils import get_field_value
|
from orchestra.models.utils import get_field_value
|
||||||
|
@ -113,21 +113,21 @@ def admin_link(*args, **kwargs):
|
||||||
return '---'
|
return '---'
|
||||||
if not getattr(obj, 'pk', None):
|
if not getattr(obj, 'pk', None):
|
||||||
return '---'
|
return '---'
|
||||||
display = kwargs.get('display')
|
display_ = kwargs.get('display')
|
||||||
if display:
|
if display_:
|
||||||
display = getattr(obj, display, display)
|
display_ = getattr(obj, display_, display_)
|
||||||
else:
|
else:
|
||||||
display = obj
|
display_ = obj
|
||||||
try:
|
try:
|
||||||
url = change_url(obj)
|
url = change_url(obj)
|
||||||
except NoReverseMatch:
|
except NoReverseMatch:
|
||||||
# Does not has admin
|
# Does not has admin
|
||||||
return str(display)
|
return str(display_)
|
||||||
extra = ''
|
extra = ''
|
||||||
if kwargs['popup']:
|
if kwargs['popup']:
|
||||||
extra = 'onclick="return showAddAnotherPopup(this);"'
|
extra = mark_safe('onclick="return showAddAnotherPopup(this);"')
|
||||||
title = "Change %s" % obj._meta.verbose_name
|
title = "Change %s" % obj._meta.verbose_name
|
||||||
return mark_safe('<a href="%s" title="%s" %s>%s</a>' % (url, title, extra, display))
|
return format_html('<a href="{}" title="{}" {}>{}</a>', url, title, extra, display_)
|
||||||
|
|
||||||
|
|
||||||
@admin_field
|
@admin_field
|
||||||
|
@ -158,7 +158,7 @@ def admin_date(*args, **kwargs):
|
||||||
date = date.strftime("%Y-%m-%d %H:%M:%S %Z")
|
date = date.strftime("%Y-%m-%d %H:%M:%S %Z")
|
||||||
else:
|
else:
|
||||||
date = date.strftime("%Y-%m-%d")
|
date = date.strftime("%Y-%m-%d")
|
||||||
return '<span title="{0}">{1}</span>'.format(date, escape(natural))
|
return format_html('<span title="{0}">{1}</span>', date, natural)
|
||||||
|
|
||||||
|
|
||||||
def get_object_from_url(modeladmin, request):
|
def get_object_from_url(modeladmin, request):
|
||||||
|
|
|
@ -175,7 +175,7 @@ def delete_related_services(modeladmin, request, queryset):
|
||||||
for model, objs in collector.model_objs.items():
|
for model, objs in collector.model_objs.items():
|
||||||
count = 0
|
count = 0
|
||||||
# discount main systemuser
|
# discount main systemuser
|
||||||
if model is modeladmin.model.main_systemuser.field.model:
|
if model is modeladmin.model.main_systemuser.field.related_model:
|
||||||
count = len(objs) - 1
|
count = len(objs) - 1
|
||||||
# Discount account
|
# Discount account
|
||||||
elif model is not modeladmin.model and model in registered_services:
|
elif model is not modeladmin.model and model in registered_services:
|
||||||
|
|
|
@ -158,6 +158,7 @@ class AccountListAdmin(AccountAdmin):
|
||||||
actions = None
|
actions = None
|
||||||
change_list_template = 'admin/accounts/account/select_account_list.html'
|
change_list_template = 'admin/accounts/account/select_account_list.html'
|
||||||
|
|
||||||
|
@mark_safe
|
||||||
def select_account(self, instance):
|
def select_account(self, instance):
|
||||||
# TODO get query string from request.META['QUERY_STRING'] to preserve filters
|
# TODO get query string from request.META['QUERY_STRING'] to preserve filters
|
||||||
context = {
|
context = {
|
||||||
|
@ -167,7 +168,6 @@ class AccountListAdmin(AccountAdmin):
|
||||||
}
|
}
|
||||||
return _('<a href="%(url)s">%(plus)s Add to %(name)s</a>') % context
|
return _('<a href="%(url)s">%(plus)s Add to %(name)s</a>') % context
|
||||||
select_account.short_description = _("account")
|
select_account.short_description = _("account")
|
||||||
select_account.allow_tags = True
|
|
||||||
select_account.admin_order_field = 'username'
|
select_account.admin_order_field = 'username'
|
||||||
|
|
||||||
def changelist_view(self, request, extra_context=None):
|
def changelist_view(self, request, extra_context=None):
|
||||||
|
@ -207,6 +207,7 @@ class AccountAdminMixin(object):
|
||||||
account = None
|
account = None
|
||||||
list_select_related = ('account',)
|
list_select_related = ('account',)
|
||||||
|
|
||||||
|
@mark_safe
|
||||||
def display_active(self, instance):
|
def display_active(self, instance):
|
||||||
if not instance.is_active:
|
if not instance.is_active:
|
||||||
return '<img src="%s" alt="False">' % static('admin/img/icon-no.svg')
|
return '<img src="%s" alt="False">' % static('admin/img/icon-no.svg')
|
||||||
|
@ -215,14 +216,12 @@ class AccountAdminMixin(object):
|
||||||
return '<img style="width:13px" src="%s" alt="False" title="%s">' % (static('admin/img/inline-delete.svg'), msg)
|
return '<img style="width:13px" src="%s" alt="False" title="%s">' % (static('admin/img/inline-delete.svg'), msg)
|
||||||
return '<img src="%s" alt="False">' % static('admin/img/icon-yes.svg')
|
return '<img src="%s" alt="False">' % static('admin/img/icon-yes.svg')
|
||||||
display_active.short_description = _("active")
|
display_active.short_description = _("active")
|
||||||
display_active.allow_tags = True
|
|
||||||
display_active.admin_order_field = 'is_active'
|
display_active.admin_order_field = 'is_active'
|
||||||
|
|
||||||
def account_link(self, instance):
|
def account_link(self, instance):
|
||||||
account = instance.account if instance.pk else self.account
|
account = instance.account if instance.pk else self.account
|
||||||
return admin_link()(account)
|
return admin_link()(account)
|
||||||
account_link.short_description = _("account")
|
account_link.short_description = _("account")
|
||||||
account_link.allow_tags = True
|
|
||||||
account_link.admin_order_field = 'account__username'
|
account_link.admin_order_field = 'account__username'
|
||||||
|
|
||||||
def get_form(self, request, obj=None, **kwargs):
|
def get_form(self, request, obj=None, **kwargs):
|
||||||
|
|
|
@ -47,7 +47,7 @@ def create_account_creation_form():
|
||||||
# Previous validation error
|
# Previous validation error
|
||||||
return
|
return
|
||||||
errors = {}
|
errors = {}
|
||||||
systemuser_model = Account.main_systemuser.field.model
|
systemuser_model = Account.main_systemuser.field.related_model
|
||||||
if systemuser_model.objects.filter(username=account.username).exists():
|
if systemuser_model.objects.filter(username=account.username).exists():
|
||||||
errors['username'] = _("A system user with this name already exists.")
|
errors['username'] = _("A system user with this name already exists.")
|
||||||
for model, key, related_kwargs, __ in create_related:
|
for model, key, related_kwargs, __ in create_related:
|
||||||
|
|
|
@ -7,6 +7,7 @@ from django.db import models
|
||||||
from django.db.models import F, Sum, Prefetch
|
from django.db.models import F, Sum, Prefetch
|
||||||
from django.db.models.functions import Coalesce
|
from django.db.models.functions import Coalesce
|
||||||
from django.templatetags.static import static
|
from django.templatetags.static import static
|
||||||
|
from django.utils.html import format_html
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.shortcuts import redirect
|
from django.shortcuts import redirect
|
||||||
|
@ -15,7 +16,7 @@ from orchestra.admin import ExtendedModelAdmin
|
||||||
from orchestra.admin.utils import admin_date, insertattr, admin_link, change_url
|
from orchestra.admin.utils import admin_date, insertattr, admin_link, change_url
|
||||||
from orchestra.contrib.accounts.actions import list_accounts
|
from orchestra.contrib.accounts.actions import list_accounts
|
||||||
from orchestra.contrib.accounts.admin import AccountAdminMixin, AccountAdmin
|
from orchestra.contrib.accounts.admin import AccountAdminMixin, AccountAdmin
|
||||||
from orchestra.forms.widgets import paddingCheckboxSelectMultiple
|
from orchestra.forms.widgets import PaddingCheckboxSelectMultiple
|
||||||
|
|
||||||
from . import settings, actions
|
from . import settings, actions
|
||||||
from .filters import (BillTypeListFilter, HasBillContactListFilter, TotalListFilter,
|
from .filters import (BillTypeListFilter, HasBillContactListFilter, TotalListFilter,
|
||||||
|
@ -67,6 +68,7 @@ class BillLineInline(admin.TabularInline):
|
||||||
|
|
||||||
order_link = admin_link('order', display='pk')
|
order_link = admin_link('order', display='pk')
|
||||||
|
|
||||||
|
@mark_safe
|
||||||
def display_total(self, line):
|
def display_total(self, line):
|
||||||
if line.pk:
|
if line.pk:
|
||||||
total = line.compute_total()
|
total = line.compute_total()
|
||||||
|
@ -78,7 +80,6 @@ class BillLineInline(admin.TabularInline):
|
||||||
return '<a href="%s" title="%s">%s <img src="%s"></img></a>' % (url, content, total, img)
|
return '<a href="%s" title="%s">%s <img src="%s"></img></a>' % (url, content, total, img)
|
||||||
return '<a href="%s">%s</a>' % (url, total)
|
return '<a href="%s">%s</a>' % (url, total)
|
||||||
display_total.short_description = _("Total")
|
display_total.short_description = _("Total")
|
||||||
display_total.allow_tags = True
|
|
||||||
|
|
||||||
def formfield_for_dbfield(self, db_field, **kwargs):
|
def formfield_for_dbfield(self, db_field, **kwargs):
|
||||||
""" Make value input widget bigger """
|
""" Make value input widget bigger """
|
||||||
|
@ -104,27 +105,26 @@ class ClosedBillLineInline(BillLineInline):
|
||||||
readonly_fields = fields
|
readonly_fields = fields
|
||||||
can_delete = False
|
can_delete = False
|
||||||
|
|
||||||
|
@mark_safe
|
||||||
def display_description(self, line):
|
def display_description(self, line):
|
||||||
descriptions = [line.description]
|
descriptions = [line.description]
|
||||||
for subline in line.sublines.all():
|
for subline in line.sublines.all():
|
||||||
descriptions.append(' '*4+subline.description)
|
descriptions.append(' ' * 4 + subline.description)
|
||||||
return '<br>'.join(descriptions)
|
return '<br>'.join(descriptions)
|
||||||
display_description.short_description = _("Description")
|
display_description.short_description = _("Description")
|
||||||
display_description.allow_tags = True
|
|
||||||
|
|
||||||
|
@mark_safe
|
||||||
def display_subtotal(self, line):
|
def display_subtotal(self, line):
|
||||||
subtotals = [' ' + str(line.subtotal)]
|
subtotals = [' ' + str(line.subtotal)]
|
||||||
for subline in line.sublines.all():
|
for subline in line.sublines.all():
|
||||||
subtotals.append(str(subline.total))
|
subtotals.append(str(subline.total))
|
||||||
return '<br>'.join(subtotals)
|
return '<br>'.join(subtotals)
|
||||||
display_subtotal.short_description = _("Subtotal")
|
display_subtotal.short_description = _("Subtotal")
|
||||||
display_subtotal.allow_tags = True
|
|
||||||
|
|
||||||
def display_total(self, line):
|
def display_total(self, line):
|
||||||
if line.pk:
|
if line.pk:
|
||||||
return line.compute_total()
|
return line.compute_total()
|
||||||
display_total.short_description = _("Total")
|
display_total.short_description = _("Total")
|
||||||
display_total.allow_tags = True
|
|
||||||
|
|
||||||
def has_add_permission(self, request):
|
def has_add_permission(self, request):
|
||||||
return False
|
return False
|
||||||
|
@ -242,6 +242,7 @@ class BillLineManagerAdmin(BillLineAdmin):
|
||||||
|
|
||||||
|
|
||||||
class BillAdminMixin(AccountAdminMixin):
|
class BillAdminMixin(AccountAdminMixin):
|
||||||
|
@mark_safe
|
||||||
def display_total_with_subtotals(self, bill):
|
def display_total_with_subtotals(self, bill):
|
||||||
if bill.pk:
|
if bill.pk:
|
||||||
currency = settings.BILLS_CURRENCY.lower()
|
currency = settings.BILLS_CURRENCY.lower()
|
||||||
|
@ -251,10 +252,10 @@ class BillAdminMixin(AccountAdminMixin):
|
||||||
subtotals.append(_("Taxes %s%% VAT %s &%s;") % (tax, subtotal[1], currency))
|
subtotals.append(_("Taxes %s%% VAT %s &%s;") % (tax, subtotal[1], currency))
|
||||||
subtotals = '\n'.join(subtotals)
|
subtotals = '\n'.join(subtotals)
|
||||||
return '<span title="%s">%s &%s;</span>' % (subtotals, bill.compute_total(), currency)
|
return '<span title="%s">%s &%s;</span>' % (subtotals, bill.compute_total(), currency)
|
||||||
display_total_with_subtotals.allow_tags = True
|
|
||||||
display_total_with_subtotals.short_description = _("total")
|
display_total_with_subtotals.short_description = _("total")
|
||||||
display_total_with_subtotals.admin_order_field = 'approx_total'
|
display_total_with_subtotals.admin_order_field = 'approx_total'
|
||||||
|
|
||||||
|
@mark_safe
|
||||||
def display_payment_state(self, bill):
|
def display_payment_state(self, bill):
|
||||||
if bill.pk:
|
if bill.pk:
|
||||||
t_opts = bill.transactions.model._meta
|
t_opts = bill.transactions.model._meta
|
||||||
|
@ -276,7 +277,6 @@ class BillAdminMixin(AccountAdminMixin):
|
||||||
color = PAYMENT_STATE_COLORS.get(bill.payment_state, 'grey')
|
color = PAYMENT_STATE_COLORS.get(bill.payment_state, 'grey')
|
||||||
return '<a href="{url}" style="color:{color}" title="{title}">{name}</a>'.format(
|
return '<a href="{url}" style="color:{color}" title="{title}">{name}</a>'.format(
|
||||||
url=url, color=color, name=state, title=title)
|
url=url, color=color, name=state, title=title)
|
||||||
display_payment_state.allow_tags = True
|
|
||||||
display_payment_state.short_description = _("Payment")
|
display_payment_state.short_description = _("Payment")
|
||||||
|
|
||||||
def get_queryset(self, request):
|
def get_queryset(self, request):
|
||||||
|
@ -376,16 +376,14 @@ class BillAdmin(BillAdminMixin, ExtendedModelAdmin):
|
||||||
|
|
||||||
def display_total(self, bill):
|
def display_total(self, bill):
|
||||||
currency = settings.BILLS_CURRENCY.lower()
|
currency = settings.BILLS_CURRENCY.lower()
|
||||||
return '%s &%s;' % (bill.compute_total(), currency)
|
return format_html('{} &{};', bill.compute_total(), currency)
|
||||||
display_total.allow_tags = True
|
|
||||||
display_total.short_description = _("total")
|
display_total.short_description = _("total")
|
||||||
display_total.admin_order_field = 'approx_total'
|
display_total.admin_order_field = 'approx_total'
|
||||||
|
|
||||||
def type_link(self, bill):
|
def type_link(self, bill):
|
||||||
bill_type = bill.type.lower()
|
bill_type = bill.type.lower()
|
||||||
url = reverse('admin:bills_%s_changelist' % bill_type)
|
url = reverse('admin:bills_%s_changelist' % bill_type)
|
||||||
return '<a href="%s">%s</a>' % (url, bill.get_type_display())
|
return format_html('<a href="{}">{}</a>', url, bill.get_type_display())
|
||||||
type_link.allow_tags = True
|
|
||||||
type_link.short_description = _("type")
|
type_link.short_description = _("type")
|
||||||
type_link.admin_order_field = 'type'
|
type_link.admin_order_field = 'type'
|
||||||
|
|
||||||
|
@ -479,7 +477,7 @@ class BillContactInline(admin.StackedInline):
|
||||||
if db_field.name == 'address':
|
if db_field.name == 'address':
|
||||||
kwargs['widget'] = forms.Textarea(attrs={'cols': 70, 'rows': 2})
|
kwargs['widget'] = forms.Textarea(attrs={'cols': 70, 'rows': 2})
|
||||||
if db_field.name == 'email_usage':
|
if db_field.name == 'email_usage':
|
||||||
kwargs['widget'] = paddingCheckboxSelectMultiple(45)
|
kwargs['widget'] = PaddingCheckboxSelectMultiple(45)
|
||||||
return super().formfield_for_dbfield(db_field, **kwargs)
|
return super().formfield_for_dbfield(db_field, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ def validate_contact(request, bill, error=True):
|
||||||
message = msg.format(relation=_("Related"), account=account, url=url)
|
message = msg.format(relation=_("Related"), account=account, url=url)
|
||||||
send(request, mark_safe(message))
|
send(request, mark_safe(message))
|
||||||
valid = False
|
valid = False
|
||||||
main = type(bill).account.field.model.objects.get_main()
|
main = type(bill).account.field.related_model.objects.get_main()
|
||||||
if not hasattr(main, 'billcontact'):
|
if not hasattr(main, 'billcontact'):
|
||||||
account = force_text(main)
|
account = force_text(main)
|
||||||
url = reverse('admin:accounts_account_change', args=(main.id,))
|
url = reverse('admin:accounts_account_change', args=(main.id,))
|
||||||
|
|
|
@ -6,7 +6,7 @@ from django.core.validators import ValidationError, RegexValidator
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models import F, Sum
|
from django.db.models import F, Sum
|
||||||
from django.db.models.functions import Coalesce
|
from django.db.models.functions import Coalesce
|
||||||
from django.template import loader, Context
|
from django.template import loader
|
||||||
from django.utils import timezone, translation
|
from django.utils import timezone, translation
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
|
@ -303,7 +303,7 @@ class Bill(models.Model):
|
||||||
with translation.override(language or self.account.language):
|
with translation.override(language or self.account.language):
|
||||||
if payment is False:
|
if payment is False:
|
||||||
payment = self.account.paymentsources.get_default()
|
payment = self.account.paymentsources.get_default()
|
||||||
context = Context({
|
context = {
|
||||||
'bill': self,
|
'bill': self,
|
||||||
'lines': self.lines.all().prefetch_related('sublines'),
|
'lines': self.lines.all().prefetch_related('sublines'),
|
||||||
'seller': self.seller,
|
'seller': self.seller,
|
||||||
|
@ -318,7 +318,7 @@ class Bill(models.Model):
|
||||||
'payment': payment and payment.get_bill_context(),
|
'payment': payment and payment.get_bill_context(),
|
||||||
'default_due_date': self.get_due_date(payment=payment),
|
'default_due_date': self.get_due_date(payment=payment),
|
||||||
'now': timezone.now(),
|
'now': timezone.now(),
|
||||||
})
|
}
|
||||||
template_name = 'BILLS_%s_TEMPLATE' % self.get_type()
|
template_name = 'BILLS_%s_TEMPLATE' % self.get_type()
|
||||||
template = getattr(settings, template_name, settings.BILLS_DEFAULT_TEMPLATE)
|
template = getattr(settings, template_name, settings.BILLS_DEFAULT_TEMPLATE)
|
||||||
bill_template = loader.get_template(template)
|
bill_template = loader.get_template(template)
|
||||||
|
|
|
@ -7,7 +7,7 @@ from orchestra.admin.actions import SendEmail
|
||||||
from orchestra.admin.utils import insertattr, change_url
|
from orchestra.admin.utils import insertattr, change_url
|
||||||
from orchestra.contrib.accounts.actions import list_accounts
|
from orchestra.contrib.accounts.actions import list_accounts
|
||||||
from orchestra.contrib.accounts.admin import AccountAdmin, AccountAdminMixin
|
from orchestra.contrib.accounts.admin import AccountAdmin, AccountAdminMixin
|
||||||
from orchestra.forms.widgets import paddingCheckboxSelectMultiple
|
from orchestra.forms.widgets import PaddingCheckboxSelectMultiple
|
||||||
|
|
||||||
from .filters import EmailUsageListFilter
|
from .filters import EmailUsageListFilter
|
||||||
from .models import Contact
|
from .models import Contact
|
||||||
|
@ -72,7 +72,7 @@ class ContactAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
if db_field.name == 'address':
|
if db_field.name == 'address':
|
||||||
kwargs['widget'] = forms.Textarea(attrs={'cols': 70, 'rows': 2})
|
kwargs['widget'] = forms.Textarea(attrs={'cols': 70, 'rows': 2})
|
||||||
if db_field.name == 'email_usage':
|
if db_field.name == 'email_usage':
|
||||||
kwargs['widget'] = paddingCheckboxSelectMultiple(130)
|
kwargs['widget'] = PaddingCheckboxSelectMultiple(130)
|
||||||
return super(ContactAdmin, self).formfield_for_dbfield(db_field, **kwargs)
|
return super(ContactAdmin, self).formfield_for_dbfield(db_field, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
@ -101,7 +101,7 @@ class ContactInline(admin.StackedInline):
|
||||||
if db_field.name == 'address':
|
if db_field.name == 'address':
|
||||||
kwargs['widget'] = forms.Textarea(attrs={'cols': 70, 'rows': 2})
|
kwargs['widget'] = forms.Textarea(attrs={'cols': 70, 'rows': 2})
|
||||||
if db_field.name == 'email_usage':
|
if db_field.name == 'email_usage':
|
||||||
kwargs['widget'] = paddingCheckboxSelectMultiple(45)
|
kwargs['widget'] = PaddingCheckboxSelectMultiple(45)
|
||||||
return super(ContactInline, self).formfield_for_dbfield(db_field, **kwargs)
|
return super(ContactInline, self).formfield_for_dbfield(db_field, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
from django.conf.urls import url
|
from django.conf.urls import url
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.contrib.auth.admin import UserAdmin
|
from django.contrib.auth.admin import UserAdmin
|
||||||
|
from django.utils.html import format_html
|
||||||
|
from django.utils.safestring import mark_safe
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from orchestra.admin import ExtendedModelAdmin, ChangePasswordAdminMixin
|
from orchestra.admin import ExtendedModelAdmin, ChangePasswordAdminMixin
|
||||||
|
@ -50,14 +52,14 @@ class DatabaseAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
||||||
list_prefetch_related = ('users',)
|
list_prefetch_related = ('users',)
|
||||||
actions = (list_accounts, save_selected)
|
actions = (list_accounts, save_selected)
|
||||||
|
|
||||||
|
@mark_safe
|
||||||
def display_users(self, db):
|
def display_users(self, db):
|
||||||
links = []
|
links = []
|
||||||
for user in db.users.all():
|
for user in db.users.all():
|
||||||
link = '<a href="%s">%s</a>' % (change_url(user), user.username)
|
link = format_html('<a href="{}">{}</a>', change_url(user), user.username)
|
||||||
links.append(link)
|
links.append(link)
|
||||||
return '<br>'.join(links)
|
return '<br>'.join(links)
|
||||||
display_users.short_description = _("Users")
|
display_users.short_description = _("Users")
|
||||||
display_users.allow_tags = True
|
|
||||||
display_users.admin_order_field = 'users__username'
|
display_users.admin_order_field = 'users__username'
|
||||||
|
|
||||||
def save_model(self, request, obj, form, change):
|
def save_model(self, request, obj, form, change):
|
||||||
|
@ -99,14 +101,14 @@ class DatabaseUserAdmin(SelectAccountAdminMixin, ChangePasswordAdminMixin, Exten
|
||||||
list_prefetch_related = ('databases',)
|
list_prefetch_related = ('databases',)
|
||||||
actions = (list_accounts, save_selected)
|
actions = (list_accounts, save_selected)
|
||||||
|
|
||||||
|
@mark_safe
|
||||||
def display_databases(self, user):
|
def display_databases(self, user):
|
||||||
links = []
|
links = []
|
||||||
for db in user.databases.all():
|
for db in user.databases.all():
|
||||||
link = '<a href="%s">%s</a>' % (change_url(db), db.name)
|
link = format_html('<a href="{}">{}</a>', change_url(db), db.name)
|
||||||
links.append(link)
|
links.append(link)
|
||||||
return '<br>'.join(links)
|
return '<br>'.join(links)
|
||||||
display_databases.short_description = _("Databases")
|
display_databases.short_description = _("Databases")
|
||||||
display_databases.allow_tags = True
|
|
||||||
display_databases.admin_order_field = 'databases__name'
|
display_databases.admin_order_field = 'databases__name'
|
||||||
|
|
||||||
def get_urls(self):
|
def get_urls(self):
|
||||||
|
|
|
@ -91,7 +91,7 @@ class DatabaseCreationForm(DatabaseUserCreationForm):
|
||||||
|
|
||||||
class ReadOnlySQLPasswordHashField(ReadOnlyPasswordHashField):
|
class ReadOnlySQLPasswordHashField(ReadOnlyPasswordHashField):
|
||||||
class ReadOnlyPasswordHashWidget(forms.Widget):
|
class ReadOnlyPasswordHashWidget(forms.Widget):
|
||||||
def render(self, name, value, attrs):
|
def render(self, name, value, attrs, renderer=None):
|
||||||
original = ReadOnlyPasswordHashField.widget().render(name, value, attrs)
|
original = ReadOnlyPasswordHashField.widget().render(name, value, attrs)
|
||||||
if 'Invalid' not in original:
|
if 'Invalid' not in original:
|
||||||
return original
|
return original
|
||||||
|
|
|
@ -3,6 +3,8 @@ from django.urls import reverse
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models.functions import Concat, Coalesce
|
from django.db.models.functions import Concat, Coalesce
|
||||||
from django.templatetags.static import static
|
from django.templatetags.static import static
|
||||||
|
from django.utils.html import format_html
|
||||||
|
from django.utils.safestring import mark_safe
|
||||||
from django.utils.translation import ugettext, ugettext_lazy as _
|
from django.utils.translation import ugettext, ugettext_lazy as _
|
||||||
|
|
||||||
from orchestra.admin import ExtendedModelAdmin
|
from orchestra.admin import ExtendedModelAdmin
|
||||||
|
@ -72,9 +74,8 @@ class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
def structured_name(self, domain):
|
def structured_name(self, domain):
|
||||||
if domain.is_top:
|
if domain.is_top:
|
||||||
return domain.name
|
return domain.name
|
||||||
return ' '*4 + domain.name
|
return mark_safe(' '*4 + domain.name)
|
||||||
structured_name.short_description = _("name")
|
structured_name.short_description = _("name")
|
||||||
structured_name.allow_tags = True
|
|
||||||
structured_name.admin_order_field = 'structured_name'
|
structured_name.admin_order_field = 'structured_name'
|
||||||
|
|
||||||
def display_is_top(self, domain):
|
def display_is_top(self, domain):
|
||||||
|
@ -83,6 +84,7 @@ class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
display_is_top.boolean = True
|
display_is_top.boolean = True
|
||||||
display_is_top.admin_order_field = 'top'
|
display_is_top.admin_order_field = 'top'
|
||||||
|
|
||||||
|
@mark_safe
|
||||||
def display_websites(self, domain):
|
def display_websites(self, domain):
|
||||||
if apps.isinstalled('orchestra.contrib.websites'):
|
if apps.isinstalled('orchestra.contrib.websites'):
|
||||||
websites = domain.websites.all()
|
websites = domain.websites.all()
|
||||||
|
@ -92,22 +94,22 @@ class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
site_link = get_on_site_link(website.get_absolute_url())
|
site_link = get_on_site_link(website.get_absolute_url())
|
||||||
admin_url = change_url(website)
|
admin_url = change_url(website)
|
||||||
title = _("Edit website")
|
title = _("Edit website")
|
||||||
link = '<a href="%s" title="%s">%s %s</a>' % (
|
link = format_html('<a href="{}" title="{}">{} {}</a>',
|
||||||
admin_url, title, website.name, site_link)
|
admin_url, title, website.name, site_link)
|
||||||
links.append(link)
|
links.append(link)
|
||||||
return '<br>'.join(links)
|
return '<br>'.join(links)
|
||||||
add_url = reverse('admin:websites_website_add')
|
add_url = reverse('admin:websites_website_add')
|
||||||
add_url += '?account=%i&domains=%i' % (domain.account_id, domain.pk)
|
add_url += '?account=%i&domains=%i' % (domain.account_id, domain.pk)
|
||||||
image = '<img src="%s"></img>' % static('orchestra/images/add.png')
|
add_link = format_html(
|
||||||
add_link = '<a href="%s" title="%s">%s</a>' % (
|
'<a href="{}" title="{}"><img src="{}" /></a>', add_url,
|
||||||
add_url, _("Add website"), image
|
_("Add website"), static('orchestra/images/add.png'),
|
||||||
)
|
)
|
||||||
return _("No website %s") % (add_link)
|
return _("No website %s") % (add_link)
|
||||||
return '---'
|
return '---'
|
||||||
display_websites.admin_order_field = 'websites__name'
|
display_websites.admin_order_field = 'websites__name'
|
||||||
display_websites.short_description = _("Websites")
|
display_websites.short_description = _("Websites")
|
||||||
display_websites.allow_tags = True
|
|
||||||
|
|
||||||
|
@mark_safe
|
||||||
def display_addresses(self, domain):
|
def display_addresses(self, domain):
|
||||||
if apps.isinstalled('orchestra.contrib.mailboxes'):
|
if apps.isinstalled('orchestra.contrib.mailboxes'):
|
||||||
add_url = reverse('admin:mailboxes_address_add')
|
add_url = reverse('admin:mailboxes_address_add')
|
||||||
|
@ -126,10 +128,9 @@ class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
return '---'
|
return '---'
|
||||||
display_addresses.short_description = _("Addresses")
|
display_addresses.short_description = _("Addresses")
|
||||||
display_addresses.admin_order_field = 'addresses__count'
|
display_addresses.admin_order_field = 'addresses__count'
|
||||||
display_addresses.allow_tags = True
|
|
||||||
|
|
||||||
|
@mark_safe
|
||||||
def implicit_records(self, domain):
|
def implicit_records(self, domain):
|
||||||
defaults = []
|
|
||||||
types = set(domain.records.values_list('type', flat=True))
|
types = set(domain.records.values_list('type', flat=True))
|
||||||
ttl = settings.DOMAINS_DEFAULT_TTL
|
ttl = settings.DOMAINS_DEFAULT_TTL
|
||||||
lines = []
|
lines = []
|
||||||
|
@ -141,14 +142,13 @@ class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
value=record.value
|
value=record.value
|
||||||
)
|
)
|
||||||
if not domain.record_is_implicit(record, types):
|
if not domain.record_is_implicit(record, types):
|
||||||
line = '<strike>%s</strike>' % line
|
line = format_html('<strike>{}</strike>', line)
|
||||||
if record.type is Record.SOA:
|
if record.type is Record.SOA:
|
||||||
lines.insert(0, line)
|
lines.insert(0, line)
|
||||||
else:
|
else:
|
||||||
lines.append(line)
|
lines.append(line)
|
||||||
return '<br>'.join(lines)
|
return '<br>'.join(lines)
|
||||||
implicit_records.short_description = _("Implicit records")
|
implicit_records.short_description = _("Implicit records")
|
||||||
implicit_records.allow_tags = True
|
|
||||||
|
|
||||||
def get_fieldsets(self, request, obj=None):
|
def get_fieldsets(self, request, obj=None):
|
||||||
""" Add SOA fields when domain is top """
|
""" Add SOA fields when domain is top """
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.utils.translation import ugettext_lazy as _
|
|
||||||
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
|
|
||||||
from django.contrib.admin.templatetags.admin_static import static
|
from django.contrib.admin.templatetags.admin_static import static
|
||||||
|
from django.contrib.admin.templatetags.admin_urls import add_preserved_filters
|
||||||
|
from django.contrib.admin.utils import unquote
|
||||||
|
from django.http import HttpResponseRedirect
|
||||||
|
from django.urls import NoReverseMatch, reverse
|
||||||
|
from django.utils.html import format_html
|
||||||
|
from django.utils.safestring import mark_safe
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from orchestra.admin.utils import admin_link, admin_date
|
from orchestra.admin.utils import admin_date, admin_link
|
||||||
|
|
||||||
|
|
||||||
class LogEntryAdmin(admin.ModelAdmin):
|
class LogEntryAdmin(admin.ModelAdmin):
|
||||||
|
@ -34,11 +36,12 @@ class LogEntryAdmin(admin.ModelAdmin):
|
||||||
user_link = admin_link('user')
|
user_link = admin_link('user')
|
||||||
display_action_time = admin_date('action_time', short_description=_("Time"))
|
display_action_time = admin_date('action_time', short_description=_("Time"))
|
||||||
|
|
||||||
|
@mark_safe
|
||||||
def display_message(self, log):
|
def display_message(self, log):
|
||||||
edit = '<a href="%(url)s"><img src="%(img)s"></img></a>' % {
|
edit = format_html('<a href="{url}"><img src="{img}"></img></a>', **{
|
||||||
'url': reverse('admin:admin_logentry_change', args=(log.pk,)),
|
'url': reverse('admin:admin_logentry_change', args=(log.pk,)),
|
||||||
'img': static('admin/img/icon-changelink.svg'),
|
'img': static('admin/img/icon-changelink.svg'),
|
||||||
}
|
})
|
||||||
if log.is_addition():
|
if log.is_addition():
|
||||||
return _('Added "%(link)s". %(edit)s') % {
|
return _('Added "%(link)s". %(edit)s') % {
|
||||||
'link': self.content_object_link(log),
|
'link': self.content_object_link(log),
|
||||||
|
@ -57,7 +60,6 @@ class LogEntryAdmin(admin.ModelAdmin):
|
||||||
}
|
}
|
||||||
display_message.short_description = _("Message")
|
display_message.short_description = _("Message")
|
||||||
display_message.admin_order_field = 'action_flag'
|
display_message.admin_order_field = 'action_flag'
|
||||||
display_message.allow_tags = True
|
|
||||||
|
|
||||||
def display_action(self, log):
|
def display_action(self, log):
|
||||||
if log.is_addition():
|
if log.is_addition():
|
||||||
|
@ -75,10 +77,9 @@ class LogEntryAdmin(admin.ModelAdmin):
|
||||||
url = reverse(view, args=(log.object_id,))
|
url = reverse(view, args=(log.object_id,))
|
||||||
except NoReverseMatch:
|
except NoReverseMatch:
|
||||||
return log.object_repr
|
return log.object_repr
|
||||||
return '<a href="%s">%s</a>' % (url, log.object_repr)
|
return format_html('<a href="{}">{}</a>', url, log.object_repr)
|
||||||
content_object_link.short_description = _("Content object")
|
content_object_link.short_description = _("Content object")
|
||||||
content_object_link.admin_order_field = 'object_repr'
|
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):
|
def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None):
|
||||||
""" Add rel_opts and object to context """
|
""" Add rel_opts and object to context """
|
||||||
|
|
|
@ -5,7 +5,8 @@ from django.urls import reverse
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
from django.utils.html import strip_tags
|
from django.utils.html import format_html, strip_tags
|
||||||
|
from django.utils.safestring import mark_safe
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from markdown import markdown
|
from markdown import markdown
|
||||||
|
|
||||||
|
@ -50,6 +51,7 @@ class MessageReadOnlyInline(admin.TabularInline):
|
||||||
'all': ('orchestra/css/hide-inline-id.css',)
|
'all': ('orchestra/css/hide-inline-id.css',)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@mark_safe
|
||||||
def content_html(self, msg):
|
def content_html(self, msg):
|
||||||
context = {
|
context = {
|
||||||
'number': msg.number,
|
'number': msg.number,
|
||||||
|
@ -58,12 +60,13 @@ class MessageReadOnlyInline(admin.TabularInline):
|
||||||
}
|
}
|
||||||
summary = _("#%(number)i Updated by %(author)s about %(time)s") % context
|
summary = _("#%(number)i Updated by %(author)s about %(time)s") % context
|
||||||
header = '<strong style="color:#666;">%s</strong><hr />' % summary
|
header = '<strong style="color:#666;">%s</strong><hr />' % summary
|
||||||
|
|
||||||
content = markdown(msg.content)
|
content = markdown(msg.content)
|
||||||
content = content.replace('>\n', '>')
|
content = content.replace('>\n', '>')
|
||||||
content = '<div style="padding-left:20px;">%s</div>' % content
|
content = '<div style="padding-left:20px;">%s</div>' % content
|
||||||
|
|
||||||
return header + content
|
return header + content
|
||||||
content_html.short_description = _("Content")
|
content_html.short_description = _("Content")
|
||||||
content_html.allow_tags = True
|
|
||||||
|
|
||||||
def has_add_permission(self, request):
|
def has_add_permission(self, request):
|
||||||
return False
|
return False
|
||||||
|
@ -111,10 +114,10 @@ class TicketInline(admin.TabularInline):
|
||||||
colored_state = admin_colored('state', colors=STATE_COLORS, bold=False)
|
colored_state = admin_colored('state', colors=STATE_COLORS, bold=False)
|
||||||
colored_priority = admin_colored('priority', colors=PRIORITY_COLORS, bold=False)
|
colored_priority = admin_colored('priority', colors=PRIORITY_COLORS, bold=False)
|
||||||
|
|
||||||
|
@mark_safe
|
||||||
def ticket_id(self, instance):
|
def ticket_id(self, instance):
|
||||||
return '<b>%s</b>' % admin_link()(instance)
|
return '<b>%s</b>' % admin_link()(instance)
|
||||||
ticket_id.short_description = '#'
|
ticket_id.short_description = '#'
|
||||||
ticket_id.allow_tags = True
|
|
||||||
|
|
||||||
|
|
||||||
class TicketAdmin(ExtendedModelAdmin):
|
class TicketAdmin(ExtendedModelAdmin):
|
||||||
|
@ -192,6 +195,7 @@ class TicketAdmin(ExtendedModelAdmin):
|
||||||
display_state = admin_colored('state', colors=STATE_COLORS, bold=False)
|
display_state = admin_colored('state', colors=STATE_COLORS, bold=False)
|
||||||
display_priority = admin_colored('priority', colors=PRIORITY_COLORS, bold=False)
|
display_priority = admin_colored('priority', colors=PRIORITY_COLORS, bold=False)
|
||||||
|
|
||||||
|
@mark_safe
|
||||||
def display_summary(self, ticket):
|
def display_summary(self, ticket):
|
||||||
context = {
|
context = {
|
||||||
'creator': admin_link('creator')(self, ticket) if ticket.creator else ticket.creator_name,
|
'creator': admin_link('creator')(self, ticket) if ticket.creator else ticket.creator_name,
|
||||||
|
@ -207,14 +211,12 @@ class TicketAdmin(ExtendedModelAdmin):
|
||||||
context['updated'] = '. Updated by %(updater)s about %(updated)s' % context
|
context['updated'] = '. Updated by %(updater)s about %(updated)s' % context
|
||||||
return '<h4>Added by %(creator)s about %(created)s%(updated)s</h4>' % context
|
return '<h4>Added by %(creator)s about %(created)s%(updated)s</h4>' % context
|
||||||
display_summary.short_description = 'Summary'
|
display_summary.short_description = 'Summary'
|
||||||
display_summary.allow_tags = True
|
|
||||||
|
|
||||||
def unbold_id(self, ticket):
|
def unbold_id(self, ticket):
|
||||||
""" Unbold id if ticket is read """
|
""" Unbold id if ticket is read """
|
||||||
if ticket.is_read_by(self.user):
|
if ticket.is_read_by(self.user):
|
||||||
return '<span style="font-weight:normal;font-size:11px;">%s</span>' % ticket.pk
|
return format_html('<span style="font-weight:normal;font-size:11px;">{}</span>', ticket.pk)
|
||||||
return ticket.pk
|
return ticket.pk
|
||||||
unbold_id.allow_tags = True
|
|
||||||
unbold_id.short_description = "#"
|
unbold_id.short_description = "#"
|
||||||
unbold_id.admin_order_field = 'id'
|
unbold_id.admin_order_field = 'id'
|
||||||
|
|
||||||
|
@ -222,8 +224,7 @@ class TicketAdmin(ExtendedModelAdmin):
|
||||||
""" Bold subject when tickets are unread for request.user """
|
""" Bold subject when tickets are unread for request.user """
|
||||||
if ticket.is_read_by(self.user):
|
if ticket.is_read_by(self.user):
|
||||||
return ticket.subject
|
return ticket.subject
|
||||||
return "<strong class='unread'>%s</strong>" % ticket.subject
|
return format_html("<strong class='unread'>{}</strong>", ticket.subject)
|
||||||
bold_subject.allow_tags = True
|
|
||||||
bold_subject.short_description = _("Subject")
|
bold_subject.short_description = _("Subject")
|
||||||
bold_subject.admin_order_field = 'subject'
|
bold_subject.admin_order_field = 'subject'
|
||||||
|
|
||||||
|
@ -297,10 +298,9 @@ class QueueAdmin(admin.ModelAdmin):
|
||||||
num = queue.tickets__count
|
num = queue.tickets__count
|
||||||
url = reverse('admin:issues_ticket_changelist')
|
url = reverse('admin:issues_ticket_changelist')
|
||||||
url += '?queue=%i' % queue.pk
|
url += '?queue=%i' % queue.pk
|
||||||
return '<a href="%s">%d</a>' % (url, num)
|
return format_html('<a href="{}">{}</a>', url, num)
|
||||||
num_tickets.short_description = _("Tickets")
|
num_tickets.short_description = _("Tickets")
|
||||||
num_tickets.admin_order_field = 'tickets__count'
|
num_tickets.admin_order_field = 'tickets__count'
|
||||||
num_tickets.allow_tags = True
|
|
||||||
|
|
||||||
def get_list_display(self, request):
|
def get_list_display(self, request):
|
||||||
""" show notifications """
|
""" show notifications """
|
||||||
|
|
|
@ -22,7 +22,7 @@ class MarkDownWidget(forms.Textarea):
|
||||||
)
|
)
|
||||||
markdown_help_text = 'HTML not allowed, you can use %s' % markdown_help_text
|
markdown_help_text = 'HTML not allowed, you can use %s' % markdown_help_text
|
||||||
|
|
||||||
def render(self, name, value, attrs):
|
def render(self, name, value, attrs, renderer=None):
|
||||||
widget_id = attrs['id'] if attrs and 'id' in attrs else 'id_%s' % name
|
widget_id = attrs['id'] if attrs and 'id' in attrs else 'id_%s' % name
|
||||||
textarea = super(MarkDownWidget, self).render(name, value, attrs)
|
textarea = super(MarkDownWidget, self).render(name, value, attrs)
|
||||||
preview = ('<a class="load-preview" href="#" data-field="{0}">preview</a>'\
|
preview = ('<a class="load-preview" href="#" data-field="{0}">preview</a>'\
|
||||||
|
|
|
@ -12,7 +12,7 @@ from .models import List
|
||||||
|
|
||||||
class RelatedDomainSerializer(AccountSerializerMixin, RelatedHyperlinkedModelSerializer):
|
class RelatedDomainSerializer(AccountSerializerMixin, RelatedHyperlinkedModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = List.address_domain.field.model
|
model = List.address_domain.field.related_model
|
||||||
fields = ('url', 'id', 'name')
|
fields = ('url', 'id', 'name')
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ from django.contrib import admin, messages
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.db.models import F, Count, Value as V
|
from django.db.models import F, Count, Value as V
|
||||||
from django.db.models.functions import Concat
|
from django.db.models.functions import Concat
|
||||||
|
from django.utils.html import format_html, format_html_join
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
@ -82,6 +83,7 @@ class MailboxAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedMo
|
||||||
if settings.MAILBOXES_LOCAL_DOMAIN:
|
if settings.MAILBOXES_LOCAL_DOMAIN:
|
||||||
type(self).actions = self.actions + (SendMailboxEmail(),)
|
type(self).actions = self.actions + (SendMailboxEmail(),)
|
||||||
|
|
||||||
|
@mark_safe
|
||||||
def display_addresses(self, mailbox):
|
def display_addresses(self, mailbox):
|
||||||
# Get from forwards
|
# Get from forwards
|
||||||
cache = caches.get_request_cache()
|
cache = caches.get_request_cache()
|
||||||
|
@ -93,7 +95,7 @@ class MailboxAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedMo
|
||||||
qs = qs.values_list('id', 'email', 'forward')
|
qs = qs.values_list('id', 'email', 'forward')
|
||||||
for addr_id, email, mbox in qs:
|
for addr_id, email, mbox in qs:
|
||||||
url = reverse('admin:mailboxes_address_change', args=(addr_id,))
|
url = reverse('admin:mailboxes_address_change', args=(addr_id,))
|
||||||
link = '<a href="%s">%s</a>' % (url, email)
|
link = format_html('<a href="{}">{}</a>', url, email)
|
||||||
try:
|
try:
|
||||||
cached_forwards[mbox].append(link)
|
cached_forwards[mbox].append(link)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
|
@ -107,26 +109,23 @@ class MailboxAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedMo
|
||||||
addresses = []
|
addresses = []
|
||||||
for addr in mailbox.addresses.all():
|
for addr in mailbox.addresses.all():
|
||||||
url = change_url(addr)
|
url = change_url(addr)
|
||||||
addresses.append('<a href="%s">%s</a>' % (url, addr.email))
|
addresses.append(format_html('<a href="{}">{}</a>', url, addr.email))
|
||||||
return '<br>'.join(addresses+forwards)
|
return '<br>'.join(addresses+forwards)
|
||||||
display_addresses.short_description = _("Addresses")
|
display_addresses.short_description = _("Addresses")
|
||||||
display_addresses.allow_tags = True
|
|
||||||
|
|
||||||
def display_forwards(self, mailbox):
|
def display_forwards(self, mailbox):
|
||||||
forwards = []
|
forwards = mailbox.get_forwards()
|
||||||
for addr in mailbox.get_forwards():
|
return format_html_join(
|
||||||
url = change_url(addr)
|
'<br>', '<a href="{}">{}</a>',
|
||||||
forwards.append('<a href="%s">%s</a>' % (url, addr.email))
|
[(change_url(addr), addr.email) for addr in forwards]
|
||||||
return '<br>'.join(forwards)
|
)
|
||||||
display_forwards.short_description = _("Forward from")
|
display_forwards.short_description = _("Forward from")
|
||||||
display_forwards.allow_tags = True
|
|
||||||
|
|
||||||
|
@mark_safe
|
||||||
def display_filtering(self, mailbox):
|
def display_filtering(self, mailbox):
|
||||||
""" becacuse of allow_tags = True """
|
|
||||||
return mailbox.get_filtering_display()
|
return mailbox.get_filtering_display()
|
||||||
display_filtering.short_description = _("Filtering")
|
display_filtering.short_description = _("Filtering")
|
||||||
display_filtering.admin_order_field = 'filtering'
|
display_filtering.admin_order_field = 'filtering'
|
||||||
display_filtering.allow_tags = True
|
|
||||||
|
|
||||||
def formfield_for_dbfield(self, db_field, **kwargs):
|
def formfield_for_dbfield(self, db_field, **kwargs):
|
||||||
if db_field.name == 'filtering':
|
if db_field.name == 'filtering':
|
||||||
|
@ -217,7 +216,7 @@ class MailboxAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedMo
|
||||||
elif obj.custom_filtering:
|
elif obj.custom_filtering:
|
||||||
messages.warning(request, msg)
|
messages.warning(request, msg)
|
||||||
super(MailboxAdmin, self).save_model(request, obj, form, change)
|
super(MailboxAdmin, self).save_model(request, obj, form, change)
|
||||||
obj.addresses = form.cleaned_data['addresses']
|
obj.addresses.set(form.cleaned_data['addresses'])
|
||||||
|
|
||||||
|
|
||||||
class AddressAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
class AddressAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
||||||
|
@ -247,29 +246,27 @@ class AddressAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
||||||
|
|
||||||
def email_link(self, address):
|
def email_link(self, address):
|
||||||
link = self.domain_link(address)
|
link = self.domain_link(address)
|
||||||
return "%s@%s" % (address.name, link)
|
return format_html("{}@{}", address.name, link)
|
||||||
email_link.short_description = _("Email")
|
email_link.short_description = _("Email")
|
||||||
email_link.allow_tags = True
|
|
||||||
|
|
||||||
def display_mailboxes(self, address):
|
def display_mailboxes(self, address):
|
||||||
boxes = []
|
boxes = address.mailboxes.all()
|
||||||
for mailbox in address.mailboxes.all():
|
return format_html_join(
|
||||||
url = change_url(mailbox)
|
'<br>', '<a href="{}">{}</a>',
|
||||||
boxes.append('<a href="%s">%s</a>' % (url, mailbox.name))
|
[(change_url(mailbox), mailbox.name) for mailbox in boxes]
|
||||||
return '<br>'.join(boxes)
|
)
|
||||||
display_mailboxes.short_description = _("Mailboxes")
|
display_mailboxes.short_description = _("Mailboxes")
|
||||||
display_mailboxes.allow_tags = True
|
|
||||||
display_mailboxes.admin_order_field = 'mailboxes__count'
|
display_mailboxes.admin_order_field = 'mailboxes__count'
|
||||||
|
|
||||||
def display_all_mailboxes(self, address):
|
def display_all_mailboxes(self, address):
|
||||||
boxes = []
|
boxes = address.get_mailboxes()
|
||||||
for mailbox in address.get_mailboxes():
|
return format_html_join(
|
||||||
url = change_url(mailbox)
|
'<br>', '<a href="{}">{}</a>',
|
||||||
boxes.append('<a href="%s">%s</a>' % (url, mailbox.name))
|
[(change_url(mailbox), mailbox.name) for mailbox in boxes]
|
||||||
return '<br>'.join(boxes)
|
)
|
||||||
display_all_mailboxes.short_description = _("Mailboxes links")
|
display_all_mailboxes.short_description = _("Mailboxes links")
|
||||||
display_all_mailboxes.allow_tags = True
|
|
||||||
|
|
||||||
|
@mark_safe
|
||||||
def display_forward(self, address):
|
def display_forward(self, address):
|
||||||
forward_mailboxes = {m.name: m for m in address.get_forward_mailboxes()}
|
forward_mailboxes = {m.name: m for m in address.get_forward_mailboxes()}
|
||||||
values = []
|
values = []
|
||||||
|
@ -281,7 +278,6 @@ class AddressAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
||||||
values.append(forward)
|
values.append(forward)
|
||||||
return '<br>'.join(values)
|
return '<br>'.join(values)
|
||||||
display_forward.short_description = _("Forward")
|
display_forward.short_description = _("Forward")
|
||||||
display_forward.allow_tags = True
|
|
||||||
display_forward.admin_order_field = 'forward'
|
display_forward.admin_order_field = 'forward'
|
||||||
|
|
||||||
def formfield_for_dbfield(self, db_field, **kwargs):
|
def formfield_for_dbfield(self, db_field, **kwargs):
|
||||||
|
|
|
@ -44,7 +44,7 @@ class Mailbox(models.Model):
|
||||||
def active(self):
|
def active(self):
|
||||||
try:
|
try:
|
||||||
return self.is_active and self.account.is_active
|
return self.is_active and self.account.is_active
|
||||||
except type(self).account.field.model.DoesNotExist:
|
except type(self).account.field.related_model.DoesNotExist:
|
||||||
return self.is_active
|
return self.is_active
|
||||||
|
|
||||||
def disable(self):
|
def disable(self):
|
||||||
|
|
|
@ -6,6 +6,8 @@ from django.contrib import admin
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.db.models import Count
|
from django.db.models import Count
|
||||||
from django.shortcuts import redirect
|
from django.shortcuts import redirect
|
||||||
|
from django.utils.html import format_html
|
||||||
|
from django.utils.safestring import mark_safe
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from orchestra.admin import ExtendedModelAdmin
|
from orchestra.admin import ExtendedModelAdmin
|
||||||
|
@ -60,11 +62,10 @@ class MessageAdmin(ExtendedModelAdmin):
|
||||||
def display_subject(self, instance):
|
def display_subject(self, instance):
|
||||||
subject = instance.subject
|
subject = instance.subject
|
||||||
if len(subject) > 64:
|
if len(subject) > 64:
|
||||||
return subject[:64] + '…'
|
return mark_safe(subject[:64] + '…')
|
||||||
return subject
|
return subject
|
||||||
display_subject.short_description = _("Subject")
|
display_subject.short_description = _("Subject")
|
||||||
display_subject.admin_order_field = 'subject'
|
display_subject.admin_order_field = 'subject'
|
||||||
display_subject.allow_tags = True
|
|
||||||
|
|
||||||
def display_retries(self, instance):
|
def display_retries(self, instance):
|
||||||
num_logs = instance.logs__count
|
num_logs = instance.logs__count
|
||||||
|
@ -74,10 +75,9 @@ class MessageAdmin(ExtendedModelAdmin):
|
||||||
else:
|
else:
|
||||||
url = reverse('admin:mailer_smtplog_changelist')
|
url = reverse('admin:mailer_smtplog_changelist')
|
||||||
url += '?&message=%i' % instance.pk
|
url += '?&message=%i' % instance.pk
|
||||||
return '<a href="%s" onclick="return showAddAnotherPopup(this);">%d</a>' % (url, instance.retries)
|
return format_html('<a href="{}" onclick="return showAddAnotherPopup(this);">{}</a>', url, instance.retries)
|
||||||
display_retries.short_description = _("Retries")
|
display_retries.short_description = _("Retries")
|
||||||
display_retries.admin_order_field = 'retries'
|
display_retries.admin_order_field = 'retries'
|
||||||
display_retries.allow_tags = True
|
|
||||||
|
|
||||||
def display_content(self, instance):
|
def display_content(self, instance):
|
||||||
part = email.message_from_string(instance.content)
|
part = email.message_from_string(instance.content)
|
||||||
|
@ -99,9 +99,8 @@ class MessageAdmin(ExtendedModelAdmin):
|
||||||
payload = payload.decode(charset)
|
payload = payload.decode(charset)
|
||||||
if part.get_content_type() == 'text/plain':
|
if part.get_content_type() == 'text/plain':
|
||||||
payload = payload.replace('\n', '<br>').replace(' ', ' ')
|
payload = payload.replace('\n', '<br>').replace(' ', ' ')
|
||||||
return payload
|
return mark_safe(payload)
|
||||||
display_content.short_description = _("Content")
|
display_content.short_description = _("Content")
|
||||||
display_content.allow_tags = True
|
|
||||||
|
|
||||||
def display_full_subject(self, instance):
|
def display_full_subject(self, instance):
|
||||||
return instance.subject
|
return instance.subject
|
||||||
|
|
|
@ -2,6 +2,7 @@ from django import forms
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.utils.html import format_html
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
@ -38,15 +39,13 @@ class MiscServiceAdmin(ExtendedModelAdmin):
|
||||||
actions = (disable, enable)
|
actions = (disable, enable)
|
||||||
|
|
||||||
def display_name(self, misc):
|
def display_name(self, misc):
|
||||||
return '<span title="%s">%s</span>' % (misc.description, misc.name)
|
return format_html('<span title="{}">{}</span>', misc.description, misc.name)
|
||||||
display_name.short_description = _("name")
|
display_name.short_description = _("name")
|
||||||
display_name.allow_tags = True
|
|
||||||
display_name.admin_order_field = 'name'
|
display_name.admin_order_field = 'name'
|
||||||
|
|
||||||
def display_verbose_name(self, misc):
|
def display_verbose_name(self, misc):
|
||||||
return '<span title="%s">%s</span>' % (misc.description, misc.verbose_name)
|
return format_html('<span title="{}">{}</span>', misc.description, misc.verbose_name)
|
||||||
display_verbose_name.short_description = _("verbose name")
|
display_verbose_name.short_description = _("verbose name")
|
||||||
display_verbose_name.allow_tags = True
|
|
||||||
display_verbose_name.admin_order_field = 'verbose_name'
|
display_verbose_name.admin_order_field = 'verbose_name'
|
||||||
|
|
||||||
def num_instances(self, misc):
|
def num_instances(self, misc):
|
||||||
|
|
|
@ -51,19 +51,18 @@ class RouteAdmin(ExtendedModelAdmin):
|
||||||
|
|
||||||
def display_model(self, route):
|
def display_model(self, route):
|
||||||
try:
|
try:
|
||||||
return escape(route.backend_class.model)
|
return route.backend_class.model
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return "<span style='color: red;'>NOT AVAILABLE</span>"
|
return mark_safe("<span style='color: red;'>NOT AVAILABLE</span>")
|
||||||
display_model.short_description = _("model")
|
display_model.short_description = _("model")
|
||||||
display_model.allow_tags = True
|
|
||||||
|
|
||||||
|
@mark_safe
|
||||||
def display_actions(self, route):
|
def display_actions(self, route):
|
||||||
try:
|
try:
|
||||||
return '<br>'.join(route.backend_class.get_actions())
|
return '<br>'.join(route.backend_class.get_actions())
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return "<span style='color: red;'>NOT AVAILABLE</span>"
|
return "<span style='color: red;'>NOT AVAILABLE</span>"
|
||||||
display_actions.short_description = _("actions")
|
display_actions.short_description = _("actions")
|
||||||
display_actions.allow_tags = True
|
|
||||||
|
|
||||||
def formfield_for_dbfield(self, db_field, **kwargs):
|
def formfield_for_dbfield(self, db_field, **kwargs):
|
||||||
""" Provides dynamic help text on backend form field """
|
""" Provides dynamic help text on backend form field """
|
||||||
|
@ -120,7 +119,6 @@ class BackendOperationInline(admin.TabularInline):
|
||||||
return _("Deleted {0}").format(operation.instance_repr or '-'.join(
|
return _("Deleted {0}").format(operation.instance_repr or '-'.join(
|
||||||
(escape(operation.content_type), escape(operation.object_id))))
|
(escape(operation.content_type), escape(operation.object_id))))
|
||||||
return link
|
return link
|
||||||
instance_link.allow_tags = True
|
|
||||||
instance_link.short_description = _("Instance")
|
instance_link.short_description = _("Instance")
|
||||||
|
|
||||||
def has_add_permission(self, *args, **kwargs):
|
def has_add_permission(self, *args, **kwargs):
|
||||||
|
@ -179,14 +177,12 @@ class ServerAdmin(ExtendedModelAdmin):
|
||||||
change_view_actions = actions
|
change_view_actions = actions
|
||||||
|
|
||||||
def display_ping(self, instance):
|
def display_ping(self, instance):
|
||||||
return self._remote_state[instance.pk][0]
|
return mark_safe(self._remote_state[instance.pk][0])
|
||||||
display_ping.short_description = _("Ping")
|
display_ping.short_description = _("Ping")
|
||||||
display_ping.allow_tags = True
|
|
||||||
|
|
||||||
def display_uptime(self, instance):
|
def display_uptime(self, instance):
|
||||||
return self._remote_state[instance.pk][1]
|
return mark_safe(self._remote_state[instance.pk][1])
|
||||||
display_uptime.short_description = _("Uptime")
|
display_uptime.short_description = _("Uptime")
|
||||||
display_uptime.allow_tags = True
|
|
||||||
|
|
||||||
def get_queryset(self, request):
|
def get_queryset(self, request):
|
||||||
""" Order by structured name and imporve performance """
|
""" Order by structured name and imporve performance """
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from django import forms
|
from django import forms
|
||||||
|
|
||||||
from orchestra.forms.widgets import SpanWidget, paddingCheckboxSelectMultiple
|
from orchestra.forms.widgets import SpanWidget, PaddingCheckboxSelectMultiple
|
||||||
|
|
||||||
|
|
||||||
class RouteForm(forms.ModelForm):
|
class RouteForm(forms.ModelForm):
|
||||||
|
@ -16,5 +16,5 @@ class RouteForm(forms.ModelForm):
|
||||||
else:
|
else:
|
||||||
self.fields['backend'].widget = SpanWidget()
|
self.fields['backend'].widget = SpanWidget()
|
||||||
actions = backend_class.actions
|
actions = backend_class.actions
|
||||||
self.fields['async_actions'].widget = paddingCheckboxSelectMultiple(45)
|
self.fields['async_actions'].widget = PaddingCheckboxSelectMultiple(45)
|
||||||
self.fields['async_actions'].choices = ((action, action) for action in actions)
|
self.fields['async_actions'].choices = ((action, action) for action in actions)
|
||||||
|
|
|
@ -51,8 +51,9 @@ class Server(models.Model):
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
self.name = self.name.strip()
|
self.name = self.name.strip()
|
||||||
self.address = self.address.strip()
|
if self.address:
|
||||||
if self.name and not self.address:
|
self.address = self.address.strip()
|
||||||
|
elif self.name:
|
||||||
validate = OrValidator(validate_ip_address, validate_hostname)
|
validate = OrValidator(validate_ip_address, validate_hostname)
|
||||||
validate_hostname(self.name)
|
validate_hostname(self.name)
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -14,7 +14,12 @@ def retrieve_state(servers):
|
||||||
state = {}
|
state = {}
|
||||||
for server, ping, uptime in zip(servers, pings, uptimes):
|
for server, ping, uptime in zip(servers, pings, uptimes):
|
||||||
ping = join(ping, silent=True)
|
ping = join(ping, silent=True)
|
||||||
ping = ping.stdout.splitlines()[-1].decode()
|
|
||||||
|
try:
|
||||||
|
ping = ping.stdout.splitlines()[-1].decode()
|
||||||
|
except IndexError:
|
||||||
|
ping = ''
|
||||||
|
|
||||||
if ping.startswith('rtt'):
|
if ping.startswith('rtt'):
|
||||||
ping = '%s ms' % ping.split('/')[4]
|
ping = '%s ms' % ping.split('/')[4]
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
|
from datetime import datetime
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.urls import reverse, NoReverseMatch
|
from django.urls import reverse, NoReverseMatch
|
||||||
from django.db.models import Prefetch
|
from django.db.models import Prefetch
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.html import escape
|
from django.utils.html import escape, format_html
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
@ -112,9 +113,8 @@ class OrderAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
display_cancelled_on = admin_date('cancelled_on')
|
display_cancelled_on = admin_date('cancelled_on')
|
||||||
|
|
||||||
def display_description(self, order):
|
def display_description(self, order):
|
||||||
return order.description[:64]
|
return format_html(order.description[:64])
|
||||||
display_description.short_description = _("Description")
|
display_description.short_description = _("Description")
|
||||||
display_description.allow_tags = True
|
|
||||||
display_description.admin_order_field = 'description'
|
display_description.admin_order_field = 'description'
|
||||||
|
|
||||||
def content_object_link(self, order):
|
def content_object_link(self, order):
|
||||||
|
@ -125,13 +125,13 @@ class OrderAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
# Does not has admin
|
# Does not has admin
|
||||||
return order.content_object_repr
|
return order.content_object_repr
|
||||||
description = str(order.content_object)
|
description = str(order.content_object)
|
||||||
return '<a href="{url}">{description}</a>'.format(
|
return format_html('<a href="{url}">{description}</a>',
|
||||||
url=url, description=description)
|
url=url, description=description)
|
||||||
return order.content_object_repr
|
return order.content_object_repr
|
||||||
content_object_link.short_description = _("Content object")
|
content_object_link.short_description = _("Content object")
|
||||||
content_object_link.allow_tags = True
|
|
||||||
content_object_link.admin_order_field = 'content_object_repr'
|
content_object_link.admin_order_field = 'content_object_repr'
|
||||||
|
|
||||||
|
@mark_safe
|
||||||
def bills_links(self, order):
|
def bills_links(self, order):
|
||||||
bills = []
|
bills = []
|
||||||
make_link = admin_link()
|
make_link = admin_link()
|
||||||
|
@ -139,7 +139,6 @@ class OrderAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
bills.append(make_link(line.bill))
|
bills.append(make_link(line.bill))
|
||||||
return '<br>'.join(bills)
|
return '<br>'.join(bills)
|
||||||
bills_links.short_description = _("Bills")
|
bills_links.short_description = _("Bills")
|
||||||
bills_links.allow_tags = True
|
|
||||||
|
|
||||||
def display_billed_until(self, order):
|
def display_billed_until(self, order):
|
||||||
billed_until = order.billed_until
|
billed_until = order.billed_until
|
||||||
|
@ -156,12 +155,12 @@ class OrderAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
red = True
|
red = True
|
||||||
elif billed_until < timezone.now().date():
|
elif billed_until < timezone.now().date():
|
||||||
red = True
|
red = True
|
||||||
color = 'style="color:red;"' if red else ''
|
color = mark_safe('style="color:red;"') if red else ''
|
||||||
return '<span title="{raw}" {color}>{human}</span>'.format(
|
return format_html(
|
||||||
|
'<span title="{raw}" {color}>{human}</span>',
|
||||||
raw=escape(str(billed_until)), color=color, human=human,
|
raw=escape(str(billed_until)), color=color, human=human,
|
||||||
)
|
)
|
||||||
display_billed_until.short_description = _("billed until")
|
display_billed_until.short_description = _("billed until")
|
||||||
display_billed_until.allow_tags = True
|
|
||||||
display_billed_until.admin_order_field = 'billed_until'
|
display_billed_until.admin_order_field = 'billed_until'
|
||||||
|
|
||||||
def display_metric(self, order):
|
def display_metric(self, order):
|
||||||
|
|
|
@ -15,7 +15,7 @@ def cancel_orders(sender, **kwargs):
|
||||||
if sender._meta.app_label not in settings.ORDERS_EXCLUDED_APPS:
|
if sender._meta.app_label not in settings.ORDERS_EXCLUDED_APPS:
|
||||||
instance = kwargs['instance']
|
instance = kwargs['instance']
|
||||||
# Account delete will delete all related orders, no need to maintain order consistency
|
# Account delete will delete all related orders, no need to maintain order consistency
|
||||||
if isinstance(instance, Order.account.field.model):
|
if isinstance(instance, Order.account.field.related_model):
|
||||||
return
|
return
|
||||||
if type(instance) in services:
|
if type(instance) in services:
|
||||||
for order in Order.objects.by_object(instance).active():
|
for order in Order.objects.by_object(instance).active():
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
|
from django.utils.html import format_html
|
||||||
|
from django.utils.safestring import mark_safe
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from orchestra.admin import ChangeViewActionsMixin, ExtendedModelAdmin
|
from orchestra.admin import ChangeViewActionsMixin, ExtendedModelAdmin
|
||||||
|
@ -154,6 +156,7 @@ class TransactionAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
||||||
return []
|
return []
|
||||||
return [action for action in actions if action.__name__ not in exclude]
|
return [action for action in actions if action.__name__ not in exclude]
|
||||||
|
|
||||||
|
@mark_safe
|
||||||
def display_state(self, obj):
|
def display_state(self, obj):
|
||||||
state = admin_colored('state', colors=STATE_COLORS)(obj)
|
state = admin_colored('state', colors=STATE_COLORS)(obj)
|
||||||
help_text = obj.get_state_help()
|
help_text = obj.get_state_help()
|
||||||
|
@ -161,7 +164,6 @@ class TransactionAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
||||||
return state
|
return state
|
||||||
display_state.admin_order_field = 'state'
|
display_state.admin_order_field = 'state'
|
||||||
display_state.short_description = _("State")
|
display_state.short_description = _("State")
|
||||||
display_state.allow_tags = True
|
|
||||||
|
|
||||||
|
|
||||||
class TransactionProcessAdmin(ChangeViewActionsMixin, admin.ModelAdmin):
|
class TransactionProcessAdmin(ChangeViewActionsMixin, admin.ModelAdmin):
|
||||||
|
@ -184,10 +186,10 @@ class TransactionProcessAdmin(ChangeViewActionsMixin, admin.ModelAdmin):
|
||||||
|
|
||||||
def file_url(self, process):
|
def file_url(self, process):
|
||||||
if process.file:
|
if process.file:
|
||||||
return '<a href="%s">%s</a>' % (process.file.url, process.file.name)
|
return format_html('<a href="{}">{}</a>', process.file.url, process.file.name)
|
||||||
file_url.allow_tags = True
|
|
||||||
file_url.admin_order_field = 'file'
|
file_url.admin_order_field = 'file'
|
||||||
|
|
||||||
|
@mark_safe
|
||||||
def display_transactions(self, process):
|
def display_transactions(self, process):
|
||||||
ids = []
|
ids = []
|
||||||
lines = []
|
lines = []
|
||||||
|
@ -207,7 +209,6 @@ class TransactionProcessAdmin(ChangeViewActionsMixin, admin.ModelAdmin):
|
||||||
url += '?process_id=%i' % process.id
|
url += '?process_id=%i' % process.id
|
||||||
return '<a href="%s">%s</a>' % (url, transactions)
|
return '<a href="%s">%s</a>' % (url, transactions)
|
||||||
display_transactions.short_description = _("Transactions")
|
display_transactions.short_description = _("Transactions")
|
||||||
display_transactions.allow_tags = True
|
|
||||||
|
|
||||||
def has_add_permission(self, *args, **kwargs):
|
def has_add_permission(self, *args, **kwargs):
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.utils.html import format_html
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from orchestra.admin import ExtendedModelAdmin
|
from orchestra.admin import ExtendedModelAdmin
|
||||||
|
@ -33,10 +34,9 @@ class PlanAdmin(ExtendedModelAdmin):
|
||||||
num = plan.contracts__count
|
num = plan.contracts__count
|
||||||
url = reverse('admin:plans_contractedplan_changelist')
|
url = reverse('admin:plans_contractedplan_changelist')
|
||||||
url += '?plan__name={}'.format(plan.name)
|
url += '?plan__name={}'.format(plan.name)
|
||||||
return '<a href="{0}">{1}</a>'.format(url, num)
|
return format_html('<a href="{0}">{1}</a>', url, num)
|
||||||
num_contracts.short_description = _("Contracts")
|
num_contracts.short_description = _("Contracts")
|
||||||
num_contracts.admin_order_field = 'contracts__count'
|
num_contracts.admin_order_field = 'contracts__count'
|
||||||
num_contracts.allow_tags = True
|
|
||||||
|
|
||||||
def get_queryset(self, request):
|
def get_queryset(self, request):
|
||||||
qs = super(PlanAdmin, self).get_queryset(request)
|
qs = super(PlanAdmin, self).get_queryset(request)
|
||||||
|
|
|
@ -11,6 +11,7 @@ from django.db.models import Q
|
||||||
from django.shortcuts import redirect
|
from django.shortcuts import redirect
|
||||||
from django.templatetags.static import static
|
from django.templatetags.static import static
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
|
from django.utils.html import format_html
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
from django.utils.translation import ungettext, ugettext_lazy as _
|
from django.utils.translation import ungettext, ugettext_lazy as _
|
||||||
|
|
||||||
|
@ -105,10 +106,9 @@ class ResourceAdmin(ExtendedModelAdmin):
|
||||||
def content_object_link(data):
|
def content_object_link(data):
|
||||||
ct = data.content_type
|
ct = data.content_type
|
||||||
url = reverse('admin:%s_%s_change' % (ct.app_label, ct.model), args=(data.object_id,))
|
url = reverse('admin:%s_%s_change' % (ct.app_label, ct.model), args=(data.object_id,))
|
||||||
return '<a href="%s">%s</a>' % (url, data.content_object_repr)
|
return format_html('<a href="{}">{}</a>', url, data.content_object_repr)
|
||||||
content_object_link.short_description = _("Content object")
|
content_object_link.short_description = _("Content object")
|
||||||
content_object_link.admin_order_field = 'content_object_repr'
|
content_object_link.admin_order_field = 'content_object_repr'
|
||||||
content_object_link.allow_tags = True
|
|
||||||
|
|
||||||
|
|
||||||
class ResourceDataAdmin(ExtendedModelAdmin):
|
class ResourceDataAdmin(ExtendedModelAdmin):
|
||||||
|
@ -155,10 +155,9 @@ class ResourceDataAdmin(ExtendedModelAdmin):
|
||||||
if rdata.used is None:
|
if rdata.used is None:
|
||||||
return ''
|
return ''
|
||||||
url = reverse('admin:resources_resourcedata_used_monitordata', args=(rdata.pk,))
|
url = reverse('admin:resources_resourcedata_used_monitordata', args=(rdata.pk,))
|
||||||
return '<a href="%s">%s %s</a>' % (url, rdata.used, rdata.unit)
|
return format_html('<a href="{}">{} {}</a>', url, rdata.used, rdata.unit)
|
||||||
display_used.short_description = _("Used")
|
display_used.short_description = _("Used")
|
||||||
display_used.admin_order_field = 'used'
|
display_used.admin_order_field = 'used'
|
||||||
display_used.allow_tags = True
|
|
||||||
|
|
||||||
def has_add_permission(self, *args, **kwargs):
|
def has_add_permission(self, *args, **kwargs):
|
||||||
return False
|
return False
|
||||||
|
@ -304,6 +303,7 @@ def resource_inline_factory(resources):
|
||||||
self.verbose_name_plural = mark_safe(_("Resources") + ' ' + link)
|
self.verbose_name_plural = mark_safe(_("Resources") + ' ' + link)
|
||||||
return super(ResourceInline, self).get_fieldsets(request, obj)
|
return super(ResourceInline, self).get_fieldsets(request, obj)
|
||||||
|
|
||||||
|
@mark_safe
|
||||||
def display_used(self, rdata):
|
def display_used(self, rdata):
|
||||||
update = ''
|
update = ''
|
||||||
history = ''
|
history = ''
|
||||||
|
@ -329,7 +329,6 @@ def resource_inline_factory(resources):
|
||||||
return _("Unknonw %s %s") % (update, history)
|
return _("Unknonw %s %s") % (update, history)
|
||||||
return _("No monitor")
|
return _("No monitor")
|
||||||
display_used.short_description = _("Used")
|
display_used.short_description = _("Used")
|
||||||
display_used.allow_tags = True
|
|
||||||
|
|
||||||
def has_add_permission(self, *args, **kwargs):
|
def has_add_permission(self, *args, **kwargs):
|
||||||
""" Hidde add another """
|
""" Hidde add another """
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
|
from django.utils.safestring import mark_safe
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from orchestra.admin import ExtendedModelAdmin, ChangePasswordAdminMixin
|
from orchestra.admin import ExtendedModelAdmin, ChangePasswordAdminMixin
|
||||||
|
@ -27,6 +28,7 @@ class SaaSAdmin(SelectPluginAdminMixin, ChangePasswordAdminMixin, AccountAdminMi
|
||||||
plugin_title = 'Software as a Service'
|
plugin_title = 'Software as a Service'
|
||||||
actions = (disable, enable, list_accounts)
|
actions = (disable, enable, list_accounts)
|
||||||
|
|
||||||
|
@mark_safe
|
||||||
def display_url(self, saas):
|
def display_url(self, saas):
|
||||||
site_domain = saas.get_site_domain()
|
site_domain = saas.get_site_domain()
|
||||||
site_link = '<a href="http://%s">%s</a>' % (site_domain, site_domain)
|
site_link = '<a href="http://%s">%s</a>' % (site_domain, site_domain)
|
||||||
|
@ -46,7 +48,6 @@ class SaaSAdmin(SelectPluginAdminMixin, ChangePasswordAdminMixin, AccountAdminMi
|
||||||
links.append(link)
|
links.append(link)
|
||||||
return '<br>'.join(links)
|
return '<br>'.join(links)
|
||||||
display_url.short_description = _("URL")
|
display_url.short_description = _("URL")
|
||||||
display_url.allow_tags = True
|
|
||||||
display_url.admin_order_field = 'name'
|
display_url.admin_order_field = 'name'
|
||||||
|
|
||||||
def get_fields(self, *args, **kwargs):
|
def get_fields(self, *args, **kwargs):
|
||||||
|
|
|
@ -42,7 +42,7 @@ def clean_custom_url(saas):
|
||||||
)
|
)
|
||||||
except Website.DoesNotExist:
|
except Website.DoesNotExist:
|
||||||
# get or create domain
|
# get or create domain
|
||||||
Domain = Website.domains.field.model
|
Domain = Website.domains.field.related_model
|
||||||
try:
|
try:
|
||||||
domain = Domain.objects.get(name=url.netloc)
|
domain = Domain.objects.get(name=url.netloc)
|
||||||
except Domain.DoesNotExist:
|
except Domain.DoesNotExist:
|
||||||
|
@ -110,7 +110,7 @@ def create_or_update_directive(saas):
|
||||||
account=account,
|
account=account,
|
||||||
)
|
)
|
||||||
except Website.DoesNotExist:
|
except Website.DoesNotExist:
|
||||||
Domain = Website.domains.field.model
|
Domain = Website.domains.field.related_model
|
||||||
domain = Domain.objects.get(name=url.netloc)
|
domain = Domain.objects.get(name=url.netloc)
|
||||||
# Create new website for custom_url
|
# Create new website for custom_url
|
||||||
tgt_server = Server.objects.get(name='web.pangea.lan')
|
tgt_server = Server.objects.get(name='web.pangea.lan')
|
||||||
|
|
|
@ -4,6 +4,7 @@ from django.contrib import admin
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.template.response import TemplateResponse
|
from django.template.response import TemplateResponse
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
from django.utils.html import format_html
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from orchestra.admin import ChangeViewActionsMixin
|
from orchestra.admin import ChangeViewActionsMixin
|
||||||
|
@ -69,10 +70,9 @@ class ServiceAdmin(ChangeViewActionsMixin, admin.ModelAdmin):
|
||||||
num = service.orders__count
|
num = service.orders__count
|
||||||
url = reverse('admin:orders_order_changelist')
|
url = reverse('admin:orders_order_changelist')
|
||||||
url += '?service__id__exact=%i&is_active=True' % service.pk
|
url += '?service__id__exact=%i&is_active=True' % service.pk
|
||||||
return '<a href="%s">%d</a>' % (url, num)
|
return format_html('<a href="{}">{}</a>', url, num)
|
||||||
num_orders.short_description = _("Orders")
|
num_orders.short_description = _("Orders")
|
||||||
num_orders.admin_order_field = 'orders__count'
|
num_orders.admin_order_field = 'orders__count'
|
||||||
num_orders.allow_tags = True
|
|
||||||
|
|
||||||
def get_queryset(self, request):
|
def get_queryset(self, request):
|
||||||
qs = super(ServiceAdmin, self).get_queryset(request)
|
qs = super(ServiceAdmin, self).get_queryset(request)
|
||||||
|
|
|
@ -61,7 +61,7 @@ class SystemUser(models.Model):
|
||||||
def active(self):
|
def active(self):
|
||||||
try:
|
try:
|
||||||
return self.is_active and self.account.is_active
|
return self.is_active and self.account.is_active
|
||||||
except type(self).account.field.model.DoesNotExist:
|
except type(self).account.field.related_model.DoesNotExist:
|
||||||
return self.is_active
|
return self.is_active
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
|
|
|
@ -2,6 +2,7 @@ from django import forms
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
|
from django.utils.safestring import mark_safe
|
||||||
from django.utils.translation import ugettext, ugettext_lazy as _
|
from django.utils.translation import ugettext, ugettext_lazy as _
|
||||||
|
|
||||||
from orchestra.admin import ExtendedModelAdmin
|
from orchestra.admin import ExtendedModelAdmin
|
||||||
|
@ -66,6 +67,7 @@ class WebAppAdmin(SelectPluginAdminMixin, AccountAdminMixin, ExtendedModelAdmin)
|
||||||
|
|
||||||
display_type = display_plugin_field('type')
|
display_type = display_plugin_field('type')
|
||||||
|
|
||||||
|
@mark_safe
|
||||||
def display_websites(self, webapp):
|
def display_websites(self, webapp):
|
||||||
websites = []
|
websites = []
|
||||||
for content in webapp.content_set.all():
|
for content in webapp.content_set.all():
|
||||||
|
@ -82,29 +84,13 @@ class WebAppAdmin(SelectPluginAdminMixin, AccountAdminMixin, ExtendedModelAdmin)
|
||||||
websites.append('<a href="%s">%s%s</a>' % (add_url, plus, ugettext("Add website")))
|
websites.append('<a href="%s">%s%s</a>' % (add_url, plus, ugettext("Add website")))
|
||||||
return '<br>'.join(websites)
|
return '<br>'.join(websites)
|
||||||
display_websites.short_description = _("web sites")
|
display_websites.short_description = _("web sites")
|
||||||
display_websites.allow_tags = True
|
|
||||||
|
|
||||||
def display_detail(self, webapp):
|
def display_detail(self, webapp):
|
||||||
try:
|
try:
|
||||||
return webapp.type_instance.get_detail()
|
return webapp.type_instance.get_detail()
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return "<span style='color:red;'>Not available</span>"
|
return mark_safe("<span style='color:red;'>Not available</span>")
|
||||||
display_detail.short_description = _("detail")
|
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 """
|
|
||||||
# if db_field.name == 'type':
|
|
||||||
# # Help text based on select widget
|
|
||||||
# kwargs['widget'] = DynamicHelpTextSelect(
|
|
||||||
# 'this.id.replace("name", "value")', self.TYPE_HELP_TEXT
|
|
||||||
# )
|
|
||||||
# kwargs['help_text'] = self.TYPE_HELP_TEXT.get(db_field.default, '')
|
|
||||||
# return super(WebAppAdmin, self).formfield_for_dbfield(db_field, **kwargs)
|
|
||||||
|
|
||||||
admin.site.register(WebApp, WebAppAdmin)
|
admin.site.register(WebApp, WebAppAdmin)
|
||||||
|
|
|
@ -2,7 +2,7 @@ import os
|
||||||
import textwrap
|
import textwrap
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
from django.template import Template, Context
|
from django.template import Template
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from orchestra.contrib.orchestration import ServiceController
|
from orchestra.contrib.orchestration import ServiceController
|
||||||
|
@ -245,7 +245,7 @@ class PHPController(WebAppServiceMixin, ServiceController):
|
||||||
php_admin_value[{{ name | safe }}] = {{ value | safe }}{% endfor %}
|
php_admin_value[{{ name | safe }}] = {{ value | safe }}{% endfor %}
|
||||||
"""
|
"""
|
||||||
))
|
))
|
||||||
return fpm_config.render(Context(context))
|
return fpm_config.render(context)
|
||||||
|
|
||||||
def get_fcgid_wrapper(self, webapp, context):
|
def get_fcgid_wrapper(self, webapp, context):
|
||||||
opt = webapp.type_instance
|
opt = webapp.type_instance
|
||||||
|
|
|
@ -3,6 +3,8 @@ from django.contrib import admin
|
||||||
from django.urls import resolve
|
from django.urls import resolve
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
|
from django.utils.html import format_html
|
||||||
|
from django.utils.safestring import mark_safe
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from orchestra.admin import ExtendedModelAdmin
|
from orchestra.admin import ExtendedModelAdmin
|
||||||
|
@ -78,6 +80,7 @@ class WebsiteAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
||||||
search_fields = ('name', 'account__username', 'domains__name', 'content__webapp__name')
|
search_fields = ('name', 'account__username', 'domains__name', 'content__webapp__name')
|
||||||
actions = (disable, enable, list_accounts)
|
actions = (disable, enable, list_accounts)
|
||||||
|
|
||||||
|
@mark_safe
|
||||||
def display_domains(self, website):
|
def display_domains(self, website):
|
||||||
domains = []
|
domains = []
|
||||||
for domain in website.domains.all():
|
for domain in website.domains.all():
|
||||||
|
@ -85,9 +88,9 @@ class WebsiteAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
||||||
domains.append('<a href="%s">%s</a>' % (url, url))
|
domains.append('<a href="%s">%s</a>' % (url, url))
|
||||||
return '<br>'.join(domains)
|
return '<br>'.join(domains)
|
||||||
display_domains.short_description = _("domains")
|
display_domains.short_description = _("domains")
|
||||||
display_domains.allow_tags = True
|
|
||||||
display_domains.admin_order_field = 'domains'
|
display_domains.admin_order_field = 'domains'
|
||||||
|
|
||||||
|
@mark_safe
|
||||||
def display_webapps(self, website):
|
def display_webapps(self, website):
|
||||||
webapps = []
|
webapps = []
|
||||||
for content in website.content_set.all():
|
for content in website.content_set.all():
|
||||||
|
@ -100,9 +103,9 @@ class WebsiteAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
||||||
pass
|
pass
|
||||||
url = change_url(webapp)
|
url = change_url(webapp)
|
||||||
name = "%s on %s" % (webapp.name, content.path or '/')
|
name = "%s on %s" % (webapp.name, content.path or '/')
|
||||||
webapps.append('<a href="%s" title="%s">%s %s</a>' % (url, detail, name, site_link))
|
webapp_info = format_html('<a href="{}" title="{}">{}</a> {}', url, detail, name, site_link)
|
||||||
|
webapps.append(webapp_info)
|
||||||
return '<br>'.join(webapps)
|
return '<br>'.join(webapps)
|
||||||
display_webapps.allow_tags = True
|
|
||||||
display_webapps.short_description = _("Web apps")
|
display_webapps.short_description = _("Web apps")
|
||||||
|
|
||||||
def formfield_for_dbfield(self, db_field, **kwargs):
|
def formfield_for_dbfield(self, db_field, **kwargs):
|
||||||
|
|
|
@ -2,7 +2,7 @@ import os
|
||||||
import re
|
import re
|
||||||
import textwrap
|
import textwrap
|
||||||
|
|
||||||
from django.template import Template, Context
|
from django.template import Template
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from orchestra.contrib.orchestration import ServiceController
|
from orchestra.contrib.orchestration import ServiceController
|
||||||
|
@ -78,7 +78,7 @@ class Apache2Controller(ServiceController):
|
||||||
{{ line | safe }}{% endfor %}
|
{{ line | safe }}{% endfor %}
|
||||||
</VirtualHost>
|
</VirtualHost>
|
||||||
""")
|
""")
|
||||||
).render(Context(context))
|
).render(context)
|
||||||
|
|
||||||
def render_redirect_https(self, context):
|
def render_redirect_https(self, context):
|
||||||
context['port'] = self.HTTP_PORT
|
context['port'] = self.HTTP_PORT
|
||||||
|
@ -96,7 +96,7 @@ class Apache2Controller(ServiceController):
|
||||||
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
|
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
|
||||||
</VirtualHost>
|
</VirtualHost>
|
||||||
""")
|
""")
|
||||||
).render(Context(context))
|
).render(context)
|
||||||
|
|
||||||
def save(self, site):
|
def save(self, site):
|
||||||
context = self.get_context(site)
|
context = self.get_context(site)
|
||||||
|
|
|
@ -13,13 +13,13 @@ from .validators import validate_domain_protocol
|
||||||
|
|
||||||
class RelatedDomainSerializer(AccountSerializerMixin, RelatedHyperlinkedModelSerializer):
|
class RelatedDomainSerializer(AccountSerializerMixin, RelatedHyperlinkedModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Website.domains.field.model
|
model = Website.domains.field.related_model
|
||||||
fields = ('url', 'id', 'name')
|
fields = ('url', 'id', 'name')
|
||||||
|
|
||||||
|
|
||||||
class RelatedWebAppSerializer(AccountSerializerMixin, RelatedHyperlinkedModelSerializer):
|
class RelatedWebAppSerializer(AccountSerializerMixin, RelatedHyperlinkedModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Content.webapp.field.model
|
model = Content.webapp.field.related_model
|
||||||
fields = ('url', 'id', 'name', 'type')
|
fields = ('url', 'id', 'name', 'type')
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,8 @@ class SpanWidget(forms.Widget):
|
||||||
self.display = kwargs.pop('display', None)
|
self.display = kwargs.pop('display', None)
|
||||||
super(SpanWidget, self).__init__(*args, **kwargs)
|
super(SpanWidget, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
def render(self, name, value, attrs=None):
|
def render(self, name, value, attrs=None, renderer=None):
|
||||||
final_attrs = self.build_attrs(attrs, name=name)
|
final_attrs = self.build_attrs(attrs, extra_attrs={'name':name})
|
||||||
original = self.original or value
|
original = self.original or value
|
||||||
display = original if self.display is None else self.display
|
display = original if self.display is None else self.display
|
||||||
# Display icon
|
# Display icon
|
||||||
|
@ -37,17 +37,17 @@ class SpanWidget(forms.Widget):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def paddingCheckboxSelectMultiple(padding):
|
class PaddingCheckboxSelectMultiple(forms.CheckboxSelectMultiple):
|
||||||
""" Ugly hack to render this widget nicely on Django admin """
|
""" Ugly hack to render this widget nicely on Django admin """
|
||||||
widget = forms.CheckboxSelectMultiple()
|
def __init__(self, padding, attrs=None, choices=()):
|
||||||
old_render = widget.render
|
super().__init__(attrs=attrs, choices=choices)
|
||||||
|
self.padding = padding
|
||||||
|
|
||||||
def render(self, *args, **kwargs):
|
def render(self, *args, **kwargs):
|
||||||
value = old_render(self, *args, **kwargs)
|
value = super().render(*args, **kwargs)
|
||||||
value = re.sub(r'^<ul id=([^>]+)>',
|
value = re.sub(r'^<ul id=([^>]+)>',
|
||||||
r'<ul id=\1 style="padding-left:%ipx">' % padding, value, 1)
|
r'<ul id=\1 style="padding-left:%ipx">' % self.padding, value, 1)
|
||||||
return mark_safe(value)
|
return mark_safe(value)
|
||||||
widget.render = render
|
|
||||||
return widget
|
|
||||||
|
|
||||||
|
|
||||||
class DynamicHelpTextSelect(forms.Select):
|
class DynamicHelpTextSelect(forms.Select):
|
||||||
|
|
|
@ -90,7 +90,7 @@ class RelatedPermission(Permission):
|
||||||
if obj is None:
|
if obj is None:
|
||||||
parent = cls
|
parent = cls
|
||||||
for relation in relations:
|
for relation in relations:
|
||||||
parent = getattr(parent, relation).field.model
|
parent = getattr(parent, relation).field.related_model
|
||||||
else:
|
else:
|
||||||
parent = functools.reduce(getattr, relations, obj)
|
parent = functools.reduce(getattr, relations, obj)
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import textwrap
|
import textwrap
|
||||||
|
|
||||||
from django.templatetags.static import static
|
from django.templatetags.static import static
|
||||||
|
from django.utils.html import format_html
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from orchestra.utils.sys import run
|
from orchestra.utils.sys import run
|
||||||
|
@ -31,6 +32,6 @@ def get_on_site_link(url):
|
||||||
context = {
|
context = {
|
||||||
'title': _("View on site %s") % url,
|
'title': _("View on site %s") % url,
|
||||||
'url': url,
|
'url': url,
|
||||||
'image': '<img src="%s"></img>' % static('orchestra/images/view-on-site.png'),
|
'image': format_html('<img src="{}"></img>', static('orchestra/images/view-on-site.png')),
|
||||||
}
|
}
|
||||||
return '<a href="%(url)s" title="%(title)s">%(image)s</a>' % context
|
return format_html('<a href="{url}" title="{title}">{image}</a>', **context)
|
||||||
|
|
|
@ -2,7 +2,6 @@ from urllib.parse import urlparse
|
||||||
|
|
||||||
from django.core.mail import EmailMultiAlternatives
|
from django.core.mail import EmailMultiAlternatives
|
||||||
from django.template.loader import render_to_string
|
from django.template.loader import render_to_string
|
||||||
from django.template import Context
|
|
||||||
|
|
||||||
|
|
||||||
def render_email_template(template, context):
|
def render_email_template(template, context):
|
||||||
|
@ -11,11 +10,8 @@ def render_email_template(template, context):
|
||||||
{% if subject %}Subject{% endif %}
|
{% if subject %}Subject{% endif %}
|
||||||
{% if message %}Email body{% endif %}
|
{% if message %}Email body{% endif %}
|
||||||
|
|
||||||
context can be a dictionary or a template.Context instance
|
context must be a dict
|
||||||
"""
|
"""
|
||||||
if isinstance(context, dict):
|
|
||||||
context = Context(context)
|
|
||||||
|
|
||||||
if not 'site' in context:
|
if not 'site' in context:
|
||||||
from orchestra import settings
|
from orchestra import settings
|
||||||
url = urlparse(settings.ORCHESTRA_SITE_URL)
|
url = urlparse(settings.ORCHESTRA_SITE_URL)
|
||||||
|
|
|
@ -12,7 +12,7 @@ ecdsa==0.11
|
||||||
Pygments==1.6
|
Pygments==1.6
|
||||||
django-filter==2.2.0
|
django-filter==2.2.0
|
||||||
jsonfield==0.9.22
|
jsonfield==0.9.22
|
||||||
python-dateutil==2.2
|
python-dateutil>=2.7.0
|
||||||
https://github.com/glic3rinu/passlib/archive/master.zip
|
https://github.com/glic3rinu/passlib/archive/master.zip
|
||||||
django-iban==0.3.0
|
django-iban==0.3.0
|
||||||
requests
|
requests
|
||||||
|
|
Loading…
Reference in New Issue