Merge pull request #8 from ribaguifi/dev/django2.1-admin

Refactor admin code to support Django 2.1
This commit is contained in:
Santiago L 2021-05-24 12:55:35 +02:00 committed by GitHub
commit 7b59931bcf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
43 changed files with 278 additions and 296 deletions

View File

@ -5,7 +5,7 @@ from django import forms
from django.contrib.admin import helpers
from django.core import validators
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 orchestra.forms.widgets import SpanWidget
@ -28,9 +28,9 @@ class AdminFormMixin(object):
' {% include "admin/includes/fieldset.html" %}'
'{% endfor %}'
)
context = Context({
context = {
'adminform': adminform
})
}
return template.render(context)
@ -71,9 +71,9 @@ class AdminFormSet(BaseModelFormSet):
</div>
</div>""")
)
context = Context({
context = {
'formset': self
})
}
return template.render(context)

View File

@ -10,7 +10,7 @@ from django.urls import reverse, NoReverseMatch
from django.db import models
from django.shortcuts import redirect
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 orchestra.models.utils import get_field_value
@ -113,21 +113,21 @@ def admin_link(*args, **kwargs):
return '---'
if not getattr(obj, 'pk', None):
return '---'
display = kwargs.get('display')
if display:
display = getattr(obj, display, display)
display_ = kwargs.get('display')
if display_:
display_ = getattr(obj, display_, display_)
else:
display = obj
display_ = obj
try:
url = change_url(obj)
except NoReverseMatch:
# Does not has admin
return str(display)
return str(display_)
extra = ''
if kwargs['popup']:
extra = 'onclick="return showAddAnotherPopup(this);"'
extra = mark_safe('onclick="return showAddAnotherPopup(this);"')
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
@ -158,7 +158,7 @@ def admin_date(*args, **kwargs):
date = date.strftime("%Y-%m-%d %H:%M:%S %Z")
else:
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):

View File

@ -175,7 +175,7 @@ def delete_related_services(modeladmin, request, queryset):
for model, objs in collector.model_objs.items():
count = 0
# 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
# Discount account
elif model is not modeladmin.model and model in registered_services:

View File

@ -158,6 +158,7 @@ class AccountListAdmin(AccountAdmin):
actions = None
change_list_template = 'admin/accounts/account/select_account_list.html'
@mark_safe
def select_account(self, instance):
# TODO get query string from request.META['QUERY_STRING'] to preserve filters
context = {
@ -167,7 +168,6 @@ class AccountListAdmin(AccountAdmin):
}
return _('<a href="%(url)s">%(plus)s Add to %(name)s</a>') % context
select_account.short_description = _("account")
select_account.allow_tags = True
select_account.admin_order_field = 'username'
def changelist_view(self, request, extra_context=None):
@ -207,6 +207,7 @@ class AccountAdminMixin(object):
account = None
list_select_related = ('account',)
@mark_safe
def display_active(self, instance):
if not instance.is_active:
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 src="%s" alt="False">' % static('admin/img/icon-yes.svg')
display_active.short_description = _("active")
display_active.allow_tags = True
display_active.admin_order_field = 'is_active'
def account_link(self, instance):
account = instance.account if instance.pk else self.account
return admin_link()(account)
account_link.short_description = _("account")
account_link.allow_tags = True
account_link.admin_order_field = 'account__username'
def get_form(self, request, obj=None, **kwargs):

View File

@ -47,7 +47,7 @@ def create_account_creation_form():
# Previous validation error
return
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():
errors['username'] = _("A system user with this name already exists.")
for model, key, related_kwargs, __ in create_related:

View File

@ -7,6 +7,7 @@ from django.db import models
from django.db.models import F, Sum, Prefetch
from django.db.models.functions import Coalesce
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_lazy as _
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.contrib.accounts.actions import list_accounts
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 .filters import (BillTypeListFilter, HasBillContactListFilter, TotalListFilter,
@ -67,6 +68,7 @@ class BillLineInline(admin.TabularInline):
order_link = admin_link('order', display='pk')
@mark_safe
def display_total(self, line):
if line.pk:
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">%s</a>' % (url, total)
display_total.short_description = _("Total")
display_total.allow_tags = True
def formfield_for_dbfield(self, db_field, **kwargs):
""" Make value input widget bigger """
@ -104,27 +105,26 @@ class ClosedBillLineInline(BillLineInline):
readonly_fields = fields
can_delete = False
@mark_safe
def display_description(self, line):
descriptions = [line.description]
for subline in line.sublines.all():
descriptions.append('&nbsp;' * 4 + subline.description)
return '<br>'.join(descriptions)
display_description.short_description = _("Description")
display_description.allow_tags = True
@mark_safe
def display_subtotal(self, line):
subtotals = ['&nbsp;' + str(line.subtotal)]
for subline in line.sublines.all():
subtotals.append(str(subline.total))
return '<br>'.join(subtotals)
display_subtotal.short_description = _("Subtotal")
display_subtotal.allow_tags = True
def display_total(self, line):
if line.pk:
return line.compute_total()
display_total.short_description = _("Total")
display_total.allow_tags = True
def has_add_permission(self, request):
return False
@ -242,6 +242,7 @@ class BillLineManagerAdmin(BillLineAdmin):
class BillAdminMixin(AccountAdminMixin):
@mark_safe
def display_total_with_subtotals(self, bill):
if bill.pk:
currency = settings.BILLS_CURRENCY.lower()
@ -251,10 +252,10 @@ class BillAdminMixin(AccountAdminMixin):
subtotals.append(_("Taxes %s%% VAT %s &%s;") % (tax, subtotal[1], currency))
subtotals = '\n'.join(subtotals)
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.admin_order_field = 'approx_total'
@mark_safe
def display_payment_state(self, bill):
if bill.pk:
t_opts = bill.transactions.model._meta
@ -276,7 +277,6 @@ class BillAdminMixin(AccountAdminMixin):
color = PAYMENT_STATE_COLORS.get(bill.payment_state, 'grey')
return '<a href="{url}" style="color:{color}" title="{title}">{name}</a>'.format(
url=url, color=color, name=state, title=title)
display_payment_state.allow_tags = True
display_payment_state.short_description = _("Payment")
def get_queryset(self, request):
@ -376,16 +376,14 @@ class BillAdmin(BillAdminMixin, ExtendedModelAdmin):
def display_total(self, bill):
currency = settings.BILLS_CURRENCY.lower()
return '%s &%s;' % (bill.compute_total(), currency)
display_total.allow_tags = True
return format_html('{} &{};', bill.compute_total(), currency)
display_total.short_description = _("total")
display_total.admin_order_field = 'approx_total'
def type_link(self, bill):
bill_type = bill.type.lower()
url = reverse('admin:bills_%s_changelist' % bill_type)
return '<a href="%s">%s</a>' % (url, bill.get_type_display())
type_link.allow_tags = True
return format_html('<a href="{}">{}</a>', url, bill.get_type_display())
type_link.short_description = _("type")
type_link.admin_order_field = 'type'
@ -479,7 +477,7 @@ class BillContactInline(admin.StackedInline):
if db_field.name == 'address':
kwargs['widget'] = forms.Textarea(attrs={'cols': 70, 'rows': 2})
if db_field.name == 'email_usage':
kwargs['widget'] = paddingCheckboxSelectMultiple(45)
kwargs['widget'] = PaddingCheckboxSelectMultiple(45)
return super().formfield_for_dbfield(db_field, **kwargs)

View File

@ -21,7 +21,7 @@ def validate_contact(request, bill, error=True):
message = msg.format(relation=_("Related"), account=account, url=url)
send(request, mark_safe(message))
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'):
account = force_text(main)
url = reverse('admin:accounts_account_change', args=(main.id,))

View File

@ -6,7 +6,7 @@ from django.core.validators import ValidationError, RegexValidator
from django.db import models
from django.db.models import F, Sum
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.encoding import force_text
from django.utils.functional import cached_property
@ -303,7 +303,7 @@ class Bill(models.Model):
with translation.override(language or self.account.language):
if payment is False:
payment = self.account.paymentsources.get_default()
context = Context({
context = {
'bill': self,
'lines': self.lines.all().prefetch_related('sublines'),
'seller': self.seller,
@ -318,7 +318,7 @@ class Bill(models.Model):
'payment': payment and payment.get_bill_context(),
'default_due_date': self.get_due_date(payment=payment),
'now': timezone.now(),
})
}
template_name = 'BILLS_%s_TEMPLATE' % self.get_type()
template = getattr(settings, template_name, settings.BILLS_DEFAULT_TEMPLATE)
bill_template = loader.get_template(template)

View File

@ -7,7 +7,7 @@ from orchestra.admin.actions import SendEmail
from orchestra.admin.utils import insertattr, change_url
from orchestra.contrib.accounts.actions import list_accounts
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 .models import Contact
@ -72,7 +72,7 @@ class ContactAdmin(AccountAdminMixin, ExtendedModelAdmin):
if db_field.name == 'address':
kwargs['widget'] = forms.Textarea(attrs={'cols': 70, 'rows': 2})
if db_field.name == 'email_usage':
kwargs['widget'] = paddingCheckboxSelectMultiple(130)
kwargs['widget'] = PaddingCheckboxSelectMultiple(130)
return super(ContactAdmin, self).formfield_for_dbfield(db_field, **kwargs)
@ -101,7 +101,7 @@ class ContactInline(admin.StackedInline):
if db_field.name == 'address':
kwargs['widget'] = forms.Textarea(attrs={'cols': 70, 'rows': 2})
if db_field.name == 'email_usage':
kwargs['widget'] = paddingCheckboxSelectMultiple(45)
kwargs['widget'] = PaddingCheckboxSelectMultiple(45)
return super(ContactInline, self).formfield_for_dbfield(db_field, **kwargs)

View File

@ -1,6 +1,8 @@
from django.conf.urls import url
from django.contrib import admin
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 orchestra.admin import ExtendedModelAdmin, ChangePasswordAdminMixin
@ -50,14 +52,14 @@ class DatabaseAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
list_prefetch_related = ('users',)
actions = (list_accounts, save_selected)
@mark_safe
def display_users(self, db):
links = []
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)
return '<br>'.join(links)
display_users.short_description = _("Users")
display_users.allow_tags = True
display_users.admin_order_field = 'users__username'
def save_model(self, request, obj, form, change):
@ -99,14 +101,14 @@ class DatabaseUserAdmin(SelectAccountAdminMixin, ChangePasswordAdminMixin, Exten
list_prefetch_related = ('databases',)
actions = (list_accounts, save_selected)
@mark_safe
def display_databases(self, user):
links = []
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)
return '<br>'.join(links)
display_databases.short_description = _("Databases")
display_databases.allow_tags = True
display_databases.admin_order_field = 'databases__name'
def get_urls(self):

View File

@ -91,7 +91,7 @@ class DatabaseCreationForm(DatabaseUserCreationForm):
class ReadOnlySQLPasswordHashField(ReadOnlyPasswordHashField):
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)
if 'Invalid' not in original:
return original

View File

@ -3,6 +3,8 @@ from django.urls import reverse
from django.db import models
from django.db.models.functions import Concat, Coalesce
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 orchestra.admin import ExtendedModelAdmin
@ -72,9 +74,8 @@ class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin):
def structured_name(self, domain):
if domain.is_top:
return domain.name
return '&nbsp;'*4 + domain.name
return mark_safe('&nbsp;'*4 + domain.name)
structured_name.short_description = _("name")
structured_name.allow_tags = True
structured_name.admin_order_field = 'structured_name'
def display_is_top(self, domain):
@ -83,6 +84,7 @@ class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin):
display_is_top.boolean = True
display_is_top.admin_order_field = 'top'
@mark_safe
def display_websites(self, domain):
if apps.isinstalled('orchestra.contrib.websites'):
websites = domain.websites.all()
@ -92,22 +94,22 @@ class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin):
site_link = get_on_site_link(website.get_absolute_url())
admin_url = change_url(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)
links.append(link)
return '<br>'.join(links)
add_url = reverse('admin:websites_website_add')
add_url += '?account=%i&domains=%i' % (domain.account_id, domain.pk)
image = '<img src="%s"></img>' % static('orchestra/images/add.png')
add_link = '<a href="%s" title="%s">%s</a>' % (
add_url, _("Add website"), image
add_link = format_html(
'<a href="{}" title="{}"><img src="{}" /></a>', add_url,
_("Add website"), static('orchestra/images/add.png'),
)
return _("No website %s") % (add_link)
return '---'
display_websites.admin_order_field = 'websites__name'
display_websites.short_description = _("Websites")
display_websites.allow_tags = True
@mark_safe
def display_addresses(self, domain):
if apps.isinstalled('orchestra.contrib.mailboxes'):
add_url = reverse('admin:mailboxes_address_add')
@ -126,10 +128,9 @@ class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin):
return '---'
display_addresses.short_description = _("Addresses")
display_addresses.admin_order_field = 'addresses__count'
display_addresses.allow_tags = True
@mark_safe
def implicit_records(self, domain):
defaults = []
types = set(domain.records.values_list('type', flat=True))
ttl = settings.DOMAINS_DEFAULT_TTL
lines = []
@ -141,14 +142,13 @@ class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin):
value=record.value
)
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:
lines.insert(0, line)
else:
lines.append(line)
return '<br>'.join(lines)
implicit_records.short_description = _("Implicit records")
implicit_records.allow_tags = True
def get_fieldsets(self, request, obj=None):
""" Add SOA fields when domain is top """

View File

@ -1,12 +1,14 @@
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_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):
@ -34,11 +36,12 @@ class LogEntryAdmin(admin.ModelAdmin):
user_link = admin_link('user')
display_action_time = admin_date('action_time', short_description=_("Time"))
@mark_safe
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,)),
'img': static('admin/img/icon-changelink.svg'),
}
})
if log.is_addition():
return _('Added "%(link)s". %(edit)s') % {
'link': self.content_object_link(log),
@ -57,7 +60,6 @@ class LogEntryAdmin(admin.ModelAdmin):
}
display_message.short_description = _("Message")
display_message.admin_order_field = 'action_flag'
display_message.allow_tags = True
def display_action(self, log):
if log.is_addition():
@ -75,10 +77,9 @@ class LogEntryAdmin(admin.ModelAdmin):
url = reverse(view, args=(log.object_id,))
except NoReverseMatch:
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.admin_order_field = 'object_repr'
content_object_link.allow_tags = True
def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None):
""" Add rel_opts and object to context """

View File

@ -5,7 +5,8 @@ from django.urls import reverse
from django.db import models
from django.http import HttpResponse
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 markdown import markdown
@ -50,6 +51,7 @@ class MessageReadOnlyInline(admin.TabularInline):
'all': ('orchestra/css/hide-inline-id.css',)
}
@mark_safe
def content_html(self, msg):
context = {
'number': msg.number,
@ -58,12 +60,13 @@ class MessageReadOnlyInline(admin.TabularInline):
}
summary = _("#%(number)i Updated by %(author)s about %(time)s") % context
header = '<strong style="color:#666;">%s</strong><hr />' % summary
content = markdown(msg.content)
content = content.replace('>\n', '>')
content = '<div style="padding-left:20px;">%s</div>' % content
return header + content
content_html.short_description = _("Content")
content_html.allow_tags = True
def has_add_permission(self, request):
return False
@ -111,10 +114,10 @@ class TicketInline(admin.TabularInline):
colored_state = admin_colored('state', colors=STATE_COLORS, bold=False)
colored_priority = admin_colored('priority', colors=PRIORITY_COLORS, bold=False)
@mark_safe
def ticket_id(self, instance):
return '<b>%s</b>' % admin_link()(instance)
ticket_id.short_description = '#'
ticket_id.allow_tags = True
class TicketAdmin(ExtendedModelAdmin):
@ -192,6 +195,7 @@ class TicketAdmin(ExtendedModelAdmin):
display_state = admin_colored('state', colors=STATE_COLORS, bold=False)
display_priority = admin_colored('priority', colors=PRIORITY_COLORS, bold=False)
@mark_safe
def display_summary(self, ticket):
context = {
'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
return '<h4>Added by %(creator)s about %(created)s%(updated)s</h4>' % context
display_summary.short_description = 'Summary'
display_summary.allow_tags = True
def unbold_id(self, ticket):
""" Unbold id if ticket is read """
if ticket.is_read_by(self.user):
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
unbold_id.allow_tags = True
unbold_id.short_description = "#"
unbold_id.admin_order_field = 'id'
@ -222,8 +224,7 @@ class TicketAdmin(ExtendedModelAdmin):
""" Bold subject when tickets are unread for request.user """
if ticket.is_read_by(self.user):
return ticket.subject
return "<strong class='unread'>%s</strong>" % ticket.subject
bold_subject.allow_tags = True
return format_html("<strong class='unread'>{}</strong>", ticket.subject)
bold_subject.short_description = _("Subject")
bold_subject.admin_order_field = 'subject'
@ -297,10 +298,9 @@ class QueueAdmin(admin.ModelAdmin):
num = queue.tickets__count
url = reverse('admin:issues_ticket_changelist')
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.admin_order_field = 'tickets__count'
num_tickets.allow_tags = True
def get_list_display(self, request):
""" show notifications """

View File

@ -22,7 +22,7 @@ class MarkDownWidget(forms.Textarea):
)
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
textarea = super(MarkDownWidget, self).render(name, value, attrs)
preview = ('<a class="load-preview" href="#" data-field="{0}">preview</a>'\

View File

@ -12,7 +12,7 @@ from .models import List
class RelatedDomainSerializer(AccountSerializerMixin, RelatedHyperlinkedModelSerializer):
class Meta:
model = List.address_domain.field.model
model = List.address_domain.field.related_model
fields = ('url', 'id', 'name')

View File

@ -6,6 +6,7 @@ from django.contrib import admin, messages
from django.urls import reverse
from django.db.models import F, Count, Value as V
from django.db.models.functions import Concat
from django.utils.html import format_html, format_html_join
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _
@ -82,6 +83,7 @@ class MailboxAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedMo
if settings.MAILBOXES_LOCAL_DOMAIN:
type(self).actions = self.actions + (SendMailboxEmail(),)
@mark_safe
def display_addresses(self, mailbox):
# Get from forwards
cache = caches.get_request_cache()
@ -93,7 +95,7 @@ class MailboxAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedMo
qs = qs.values_list('id', 'email', 'forward')
for addr_id, email, mbox in qs:
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:
cached_forwards[mbox].append(link)
except KeyError:
@ -107,26 +109,23 @@ class MailboxAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedMo
addresses = []
for addr in mailbox.addresses.all():
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)
display_addresses.short_description = _("Addresses")
display_addresses.allow_tags = True
def display_forwards(self, mailbox):
forwards = []
for addr in mailbox.get_forwards():
url = change_url(addr)
forwards.append('<a href="%s">%s</a>' % (url, addr.email))
return '<br>'.join(forwards)
forwards = mailbox.get_forwards()
return format_html_join(
'<br>', '<a href="{}">{}</a>',
[(change_url(addr), addr.email) for addr in forwards]
)
display_forwards.short_description = _("Forward from")
display_forwards.allow_tags = True
@mark_safe
def display_filtering(self, mailbox):
""" becacuse of allow_tags = True """
return mailbox.get_filtering_display()
display_filtering.short_description = _("Filtering")
display_filtering.admin_order_field = 'filtering'
display_filtering.allow_tags = True
def formfield_for_dbfield(self, db_field, **kwargs):
if db_field.name == 'filtering':
@ -217,7 +216,7 @@ class MailboxAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedMo
elif obj.custom_filtering:
messages.warning(request, msg)
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):
@ -247,29 +246,27 @@ class AddressAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
def email_link(self, 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.allow_tags = True
def display_mailboxes(self, address):
boxes = []
for mailbox in address.mailboxes.all():
url = change_url(mailbox)
boxes.append('<a href="%s">%s</a>' % (url, mailbox.name))
return '<br>'.join(boxes)
boxes = address.mailboxes.all()
return format_html_join(
'<br>', '<a href="{}">{}</a>',
[(change_url(mailbox), mailbox.name) for mailbox in boxes]
)
display_mailboxes.short_description = _("Mailboxes")
display_mailboxes.allow_tags = True
display_mailboxes.admin_order_field = 'mailboxes__count'
def display_all_mailboxes(self, address):
boxes = []
for mailbox in address.get_mailboxes():
url = change_url(mailbox)
boxes.append('<a href="%s">%s</a>' % (url, mailbox.name))
return '<br>'.join(boxes)
boxes = address.get_mailboxes()
return format_html_join(
'<br>', '<a href="{}">{}</a>',
[(change_url(mailbox), mailbox.name) for mailbox in boxes]
)
display_all_mailboxes.short_description = _("Mailboxes links")
display_all_mailboxes.allow_tags = True
@mark_safe
def display_forward(self, address):
forward_mailboxes = {m.name: m for m in address.get_forward_mailboxes()}
values = []
@ -281,7 +278,6 @@ class AddressAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
values.append(forward)
return '<br>'.join(values)
display_forward.short_description = _("Forward")
display_forward.allow_tags = True
display_forward.admin_order_field = 'forward'
def formfield_for_dbfield(self, db_field, **kwargs):

View File

@ -44,7 +44,7 @@ class Mailbox(models.Model):
def active(self):
try:
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
def disable(self):

View File

@ -6,6 +6,8 @@ from django.contrib import admin
from django.urls import reverse
from django.db.models import Count
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 orchestra.admin import ExtendedModelAdmin
@ -60,11 +62,10 @@ class MessageAdmin(ExtendedModelAdmin):
def display_subject(self, instance):
subject = instance.subject
if len(subject) > 64:
return subject[:64] + '&hellip;'
return mark_safe(subject[:64] + '&hellip;')
return subject
display_subject.short_description = _("Subject")
display_subject.admin_order_field = 'subject'
display_subject.allow_tags = True
def display_retries(self, instance):
num_logs = instance.logs__count
@ -74,10 +75,9 @@ class MessageAdmin(ExtendedModelAdmin):
else:
url = reverse('admin:mailer_smtplog_changelist')
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.admin_order_field = 'retries'
display_retries.allow_tags = True
def display_content(self, instance):
part = email.message_from_string(instance.content)
@ -99,9 +99,8 @@ class MessageAdmin(ExtendedModelAdmin):
payload = payload.decode(charset)
if part.get_content_type() == 'text/plain':
payload = payload.replace('\n', '<br>').replace(' ', '&nbsp;')
return payload
return mark_safe(payload)
display_content.short_description = _("Content")
display_content.allow_tags = True
def display_full_subject(self, instance):
return instance.subject

View File

@ -2,6 +2,7 @@ from django import forms
from django.contrib import admin
from django.urls import reverse
from django.db import models
from django.utils.html import format_html
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _
@ -38,15 +39,13 @@ class MiscServiceAdmin(ExtendedModelAdmin):
actions = (disable, enable)
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.allow_tags = True
display_name.admin_order_field = 'name'
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.allow_tags = True
display_verbose_name.admin_order_field = 'verbose_name'
def num_instances(self, misc):

View File

@ -51,19 +51,18 @@ class RouteAdmin(ExtendedModelAdmin):
def display_model(self, route):
try:
return escape(route.backend_class.model)
return route.backend_class.model
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.allow_tags = True
@mark_safe
def display_actions(self, route):
try:
return '<br>'.join(route.backend_class.get_actions())
except KeyError:
return "<span style='color: red;'>NOT AVAILABLE</span>"
display_actions.short_description = _("actions")
display_actions.allow_tags = True
def formfield_for_dbfield(self, db_field, **kwargs):
""" 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(
(escape(operation.content_type), escape(operation.object_id))))
return link
instance_link.allow_tags = True
instance_link.short_description = _("Instance")
def has_add_permission(self, *args, **kwargs):
@ -179,14 +177,12 @@ class ServerAdmin(ExtendedModelAdmin):
change_view_actions = actions
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.allow_tags = True
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.allow_tags = True
def get_queryset(self, request):
""" Order by structured name and imporve performance """

View File

@ -1,6 +1,6 @@
from django import forms
from orchestra.forms.widgets import SpanWidget, paddingCheckboxSelectMultiple
from orchestra.forms.widgets import SpanWidget, PaddingCheckboxSelectMultiple
class RouteForm(forms.ModelForm):
@ -16,5 +16,5 @@ class RouteForm(forms.ModelForm):
else:
self.fields['backend'].widget = SpanWidget()
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)

View File

@ -51,8 +51,9 @@ class Server(models.Model):
def clean(self):
self.name = self.name.strip()
if self.address:
self.address = self.address.strip()
if self.name and not self.address:
elif self.name:
validate = OrValidator(validate_ip_address, validate_hostname)
validate_hostname(self.name)
try:

View File

@ -14,7 +14,12 @@ def retrieve_state(servers):
state = {}
for server, ping, uptime in zip(servers, pings, uptimes):
ping = join(ping, silent=True)
try:
ping = ping.stdout.splitlines()[-1].decode()
except IndexError:
ping = ''
if ping.startswith('rtt'):
ping = '%s ms' % ping.split('/')[4]
else:

View File

@ -1,9 +1,10 @@
from datetime import datetime
from django import forms
from django.contrib import admin
from django.urls import reverse, NoReverseMatch
from django.db.models import Prefetch
from django.utils import timezone
from django.utils.html import escape
from django.utils.html import escape, format_html
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _
@ -112,9 +113,8 @@ class OrderAdmin(AccountAdminMixin, ExtendedModelAdmin):
display_cancelled_on = admin_date('cancelled_on')
def display_description(self, order):
return order.description[:64]
return format_html(order.description[:64])
display_description.short_description = _("Description")
display_description.allow_tags = True
display_description.admin_order_field = 'description'
def content_object_link(self, order):
@ -125,13 +125,13 @@ class OrderAdmin(AccountAdminMixin, ExtendedModelAdmin):
# Does not has admin
return order.content_object_repr
description = str(order.content_object)
return '<a href="{url}">{description}</a>'.format(
return format_html('<a href="{url}">{description}</a>',
url=url, description=description)
return order.content_object_repr
content_object_link.short_description = _("Content object")
content_object_link.allow_tags = True
content_object_link.admin_order_field = 'content_object_repr'
@mark_safe
def bills_links(self, order):
bills = []
make_link = admin_link()
@ -139,7 +139,6 @@ class OrderAdmin(AccountAdminMixin, ExtendedModelAdmin):
bills.append(make_link(line.bill))
return '<br>'.join(bills)
bills_links.short_description = _("Bills")
bills_links.allow_tags = True
def display_billed_until(self, order):
billed_until = order.billed_until
@ -156,12 +155,12 @@ class OrderAdmin(AccountAdminMixin, ExtendedModelAdmin):
red = True
elif billed_until < timezone.now().date():
red = True
color = 'style="color:red;"' if red else ''
return '<span title="{raw}" {color}>{human}</span>'.format(
color = mark_safe('style="color:red;"') if red else ''
return format_html(
'<span title="{raw}" {color}>{human}</span>',
raw=escape(str(billed_until)), color=color, human=human,
)
display_billed_until.short_description = _("billed until")
display_billed_until.allow_tags = True
display_billed_until.admin_order_field = 'billed_until'
def display_metric(self, order):

View File

@ -15,7 +15,7 @@ def cancel_orders(sender, **kwargs):
if sender._meta.app_label not in settings.ORDERS_EXCLUDED_APPS:
instance = kwargs['instance']
# 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
if type(instance) in services:
for order in Order.objects.by_object(instance).active():

View File

@ -1,6 +1,8 @@
from django.contrib import admin
from django.urls import reverse
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 orchestra.admin import ChangeViewActionsMixin, ExtendedModelAdmin
@ -154,6 +156,7 @@ class TransactionAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
return []
return [action for action in actions if action.__name__ not in exclude]
@mark_safe
def display_state(self, obj):
state = admin_colored('state', colors=STATE_COLORS)(obj)
help_text = obj.get_state_help()
@ -161,7 +164,6 @@ class TransactionAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
return state
display_state.admin_order_field = 'state'
display_state.short_description = _("State")
display_state.allow_tags = True
class TransactionProcessAdmin(ChangeViewActionsMixin, admin.ModelAdmin):
@ -184,10 +186,10 @@ class TransactionProcessAdmin(ChangeViewActionsMixin, admin.ModelAdmin):
def file_url(self, process):
if process.file:
return '<a href="%s">%s</a>' % (process.file.url, process.file.name)
file_url.allow_tags = True
return format_html('<a href="{}">{}</a>', process.file.url, process.file.name)
file_url.admin_order_field = 'file'
@mark_safe
def display_transactions(self, process):
ids = []
lines = []
@ -207,7 +209,6 @@ class TransactionProcessAdmin(ChangeViewActionsMixin, admin.ModelAdmin):
url += '?process_id=%i' % process.id
return '<a href="%s">%s</a>' % (url, transactions)
display_transactions.short_description = _("Transactions")
display_transactions.allow_tags = True
def has_add_permission(self, *args, **kwargs):
return False

View File

@ -1,6 +1,7 @@
from django.contrib import admin
from django.urls import reverse
from django.db import models
from django.utils.html import format_html
from django.utils.translation import ugettext_lazy as _
from orchestra.admin import ExtendedModelAdmin
@ -33,10 +34,9 @@ class PlanAdmin(ExtendedModelAdmin):
num = plan.contracts__count
url = reverse('admin:plans_contractedplan_changelist')
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.admin_order_field = 'contracts__count'
num_contracts.allow_tags = True
def get_queryset(self, request):
qs = super(PlanAdmin, self).get_queryset(request)

View File

@ -11,6 +11,7 @@ from django.db.models import Q
from django.shortcuts import redirect
from django.templatetags.static import static
from django.utils.functional import cached_property
from django.utils.html import format_html
from django.utils.safestring import mark_safe
from django.utils.translation import ungettext, ugettext_lazy as _
@ -105,10 +106,9 @@ class ResourceAdmin(ExtendedModelAdmin):
def content_object_link(data):
ct = data.content_type
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.admin_order_field = 'content_object_repr'
content_object_link.allow_tags = True
class ResourceDataAdmin(ExtendedModelAdmin):
@ -155,10 +155,9 @@ class ResourceDataAdmin(ExtendedModelAdmin):
if rdata.used is None:
return ''
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.admin_order_field = 'used'
display_used.allow_tags = True
def has_add_permission(self, *args, **kwargs):
return False
@ -304,6 +303,7 @@ def resource_inline_factory(resources):
self.verbose_name_plural = mark_safe(_("Resources") + ' ' + link)
return super(ResourceInline, self).get_fieldsets(request, obj)
@mark_safe
def display_used(self, rdata):
update = ''
history = ''
@ -329,7 +329,6 @@ def resource_inline_factory(resources):
return _("Unknonw %s %s") % (update, history)
return _("No monitor")
display_used.short_description = _("Used")
display_used.allow_tags = True
def has_add_permission(self, *args, **kwargs):
""" Hidde add another """

View File

@ -1,5 +1,6 @@
from django.contrib import admin
from django.core.exceptions import ObjectDoesNotExist
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _
from orchestra.admin import ExtendedModelAdmin, ChangePasswordAdminMixin
@ -27,6 +28,7 @@ class SaaSAdmin(SelectPluginAdminMixin, ChangePasswordAdminMixin, AccountAdminMi
plugin_title = 'Software as a Service'
actions = (disable, enable, list_accounts)
@mark_safe
def display_url(self, saas):
site_domain = saas.get_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)
return '<br>'.join(links)
display_url.short_description = _("URL")
display_url.allow_tags = True
display_url.admin_order_field = 'name'
def get_fields(self, *args, **kwargs):

View File

@ -42,7 +42,7 @@ def clean_custom_url(saas):
)
except Website.DoesNotExist:
# get or create domain
Domain = Website.domains.field.model
Domain = Website.domains.field.related_model
try:
domain = Domain.objects.get(name=url.netloc)
except Domain.DoesNotExist:
@ -110,7 +110,7 @@ def create_or_update_directive(saas):
account=account,
)
except Website.DoesNotExist:
Domain = Website.domains.field.model
Domain = Website.domains.field.related_model
domain = Domain.objects.get(name=url.netloc)
# Create new website for custom_url
tgt_server = Server.objects.get(name='web.pangea.lan')

View File

@ -4,6 +4,7 @@ from django.contrib import admin
from django.urls import reverse
from django.template.response import TemplateResponse
from django.utils import timezone
from django.utils.html import format_html
from django.utils.translation import ugettext_lazy as _
from orchestra.admin import ChangeViewActionsMixin
@ -69,10 +70,9 @@ class ServiceAdmin(ChangeViewActionsMixin, admin.ModelAdmin):
num = service.orders__count
url = reverse('admin:orders_order_changelist')
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.admin_order_field = 'orders__count'
num_orders.allow_tags = True
def get_queryset(self, request):
qs = super(ServiceAdmin, self).get_queryset(request)

View File

@ -61,7 +61,7 @@ class SystemUser(models.Model):
def active(self):
try:
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
@cached_property

View File

@ -2,6 +2,7 @@ from django import forms
from django.contrib import admin
from django.urls import reverse
from django.utils.encoding import force_text
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext, ugettext_lazy as _
from orchestra.admin import ExtendedModelAdmin
@ -66,6 +67,7 @@ class WebAppAdmin(SelectPluginAdminMixin, AccountAdminMixin, ExtendedModelAdmin)
display_type = display_plugin_field('type')
@mark_safe
def display_websites(self, webapp):
websites = []
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")))
return '<br>'.join(websites)
display_websites.short_description = _("web sites")
display_websites.allow_tags = True
def display_detail(self, webapp):
try:
return webapp.type_instance.get_detail()
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.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)

View File

@ -2,7 +2,7 @@ import os
import textwrap
from collections import OrderedDict
from django.template import Template, Context
from django.template import Template
from django.utils.translation import ugettext_lazy as _
from orchestra.contrib.orchestration import ServiceController
@ -245,7 +245,7 @@ class PHPController(WebAppServiceMixin, ServiceController):
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):
opt = webapp.type_instance

View File

@ -3,6 +3,8 @@ from django.contrib import admin
from django.urls import resolve
from django.db.models import Q
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 orchestra.admin import ExtendedModelAdmin
@ -78,6 +80,7 @@ class WebsiteAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
search_fields = ('name', 'account__username', 'domains__name', 'content__webapp__name')
actions = (disable, enable, list_accounts)
@mark_safe
def display_domains(self, website):
domains = []
for domain in website.domains.all():
@ -85,9 +88,9 @@ class WebsiteAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
domains.append('<a href="%s">%s</a>' % (url, url))
return '<br>'.join(domains)
display_domains.short_description = _("domains")
display_domains.allow_tags = True
display_domains.admin_order_field = 'domains'
@mark_safe
def display_webapps(self, website):
webapps = []
for content in website.content_set.all():
@ -100,9 +103,9 @@ class WebsiteAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
pass
url = change_url(webapp)
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)
display_webapps.allow_tags = True
display_webapps.short_description = _("Web apps")
def formfield_for_dbfield(self, db_field, **kwargs):

View File

@ -2,7 +2,7 @@ import os
import re
import textwrap
from django.template import Template, Context
from django.template import Template
from django.utils.translation import ugettext_lazy as _
from orchestra.contrib.orchestration import ServiceController
@ -78,7 +78,7 @@ class Apache2Controller(ServiceController):
{{ line | safe }}{% endfor %}
</VirtualHost>
""")
).render(Context(context))
).render(context)
def render_redirect_https(self, context):
context['port'] = self.HTTP_PORT
@ -96,7 +96,7 @@ class Apache2Controller(ServiceController):
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
</VirtualHost>
""")
).render(Context(context))
).render(context)
def save(self, site):
context = self.get_context(site)

View File

@ -13,13 +13,13 @@ from .validators import validate_domain_protocol
class RelatedDomainSerializer(AccountSerializerMixin, RelatedHyperlinkedModelSerializer):
class Meta:
model = Website.domains.field.model
model = Website.domains.field.related_model
fields = ('url', 'id', 'name')
class RelatedWebAppSerializer(AccountSerializerMixin, RelatedHyperlinkedModelSerializer):
class Meta:
model = Content.webapp.field.model
model = Content.webapp.field.related_model
fields = ('url', 'id', 'name', 'type')

View File

@ -18,8 +18,8 @@ class SpanWidget(forms.Widget):
self.display = kwargs.pop('display', None)
super(SpanWidget, self).__init__(*args, **kwargs)
def render(self, name, value, attrs=None):
final_attrs = self.build_attrs(attrs, name=name)
def render(self, name, value, attrs=None, renderer=None):
final_attrs = self.build_attrs(attrs, extra_attrs={'name':name})
original = self.original or value
display = original if self.display is None else self.display
# Display icon
@ -37,17 +37,17 @@ class SpanWidget(forms.Widget):
return False
def paddingCheckboxSelectMultiple(padding):
class PaddingCheckboxSelectMultiple(forms.CheckboxSelectMultiple):
""" Ugly hack to render this widget nicely on Django admin """
widget = forms.CheckboxSelectMultiple()
old_render = widget.render
def __init__(self, padding, attrs=None, choices=()):
super().__init__(attrs=attrs, choices=choices)
self.padding = padding
def render(self, *args, **kwargs):
value = old_render(self, *args, **kwargs)
value = super().render(*args, **kwargs)
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)
widget.render = render
return widget
class DynamicHelpTextSelect(forms.Select):

View File

@ -90,7 +90,7 @@ class RelatedPermission(Permission):
if obj is None:
parent = cls
for relation in relations:
parent = getattr(parent, relation).field.model
parent = getattr(parent, relation).field.related_model
else:
parent = functools.reduce(getattr, relations, obj)

View File

@ -1,6 +1,7 @@
import textwrap
from django.templatetags.static import static
from django.utils.html import format_html
from django.utils.translation import ugettext_lazy as _
from orchestra.utils.sys import run
@ -31,6 +32,6 @@ def get_on_site_link(url):
context = {
'title': _("View on site %s") % 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)

View File

@ -2,7 +2,6 @@ from urllib.parse import urlparse
from django.core.mail import EmailMultiAlternatives
from django.template.loader import render_to_string
from django.template import Context
def render_email_template(template, context):
@ -11,11 +10,8 @@ def render_email_template(template, context):
{% if subject %}Subject{% 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:
from orchestra import settings
url = urlparse(settings.ORCHESTRA_SITE_URL)

View File

@ -12,7 +12,7 @@ ecdsa==0.11
Pygments==1.6
django-filter==2.2.0
jsonfield==0.9.22
python-dateutil==2.2
python-dateutil>=2.7.0
https://github.com/glic3rinu/passlib/archive/master.zip
django-iban==0.3.0
requests