Improved admin performance
This commit is contained in:
parent
e388346f9a
commit
201608c49c
12
TODO.md
12
TODO.md
|
@ -435,7 +435,7 @@ mkhomedir_helper or create ssh homes with bash.rc and such
|
||||||
|
|
||||||
|
|
||||||
# DOmain show implicit records
|
# DOmain show implicit records
|
||||||
# if not database_ready(): schedule a retry in 60 seconds, otherwise resources and other dynamic content gets fucked, maybe attach some 'signal' when first query goes trough
|
# if not database_ready(): schedule a retry in 60 seconds, otherwise resources and other dynamic content gets fucked, maybe attach some 'signal' when first query goes trough
|
||||||
with database_ready:
|
with database_ready:
|
||||||
shit_happend, otherwise schedule for first query
|
shit_happend, otherwise schedule for first query
|
||||||
# Entry.objects.filter()[:1].first() (LIMIT 1)
|
# Entry.objects.filter()[:1].first() (LIMIT 1)
|
||||||
|
@ -443,24 +443,14 @@ mkhomedir_helper or create ssh homes with bash.rc and such
|
||||||
# put "Coordinate Apache restart" inside a bash function for clarity
|
# put "Coordinate Apache restart" inside a bash function for clarity
|
||||||
|
|
||||||
|
|
||||||
# mailscanner phishing, spam, whitelist choices
|
|
||||||
|
|
||||||
|
|
||||||
# show base and total desglosed
|
# show base and total desglosed
|
||||||
|
|
||||||
|
|
||||||
# Reverse lOgHistory order by date (lastest first)
|
# Reverse lOgHistory order by date (lastest first)
|
||||||
|
|
||||||
|
|
||||||
* setuppostgres use porject_name for db name and user instead of orchestra
|
* setuppostgres use porject_name for db name and user instead of orchestra
|
||||||
|
|
||||||
|
|
||||||
# POSTFIX web traffic monitor '": uid=" from=<%(user)s>'
|
# POSTFIX web traffic monitor '": uid=" from=<%(user)s>'
|
||||||
|
|
||||||
# Automatically re-run backends until success? only timedout executions?
|
# Automatically re-run backends until success? only timedout executions?
|
||||||
# TODO save serialized versions ob backendoperation.instance in order to allow backend reexecution of deleted objects
|
# TODO save serialized versions ob backendoperation.instance in order to allow backend reexecution of deleted objects
|
||||||
|
|
||||||
|
|
||||||
# INDEXES for most used queries: account FK
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -64,10 +64,10 @@ class BillLineInline(admin.TabularInline):
|
||||||
kwargs['widget'] = forms.TextInput(attrs={'size':'50'})
|
kwargs['widget'] = forms.TextInput(attrs={'size':'50'})
|
||||||
elif db_field.name not in ('start_on', 'end_on'):
|
elif db_field.name not in ('start_on', 'end_on'):
|
||||||
kwargs['widget'] = forms.TextInput(attrs={'size':'6'})
|
kwargs['widget'] = forms.TextInput(attrs={'size':'6'})
|
||||||
return super(BillLineInline, self).formfield_for_dbfield(db_field, **kwargs)
|
return super().formfield_for_dbfield(db_field, **kwargs)
|
||||||
|
|
||||||
def get_queryset(self, request):
|
def get_queryset(self, request):
|
||||||
qs = super(BillLineInline, self).get_queryset(request)
|
qs = super().get_queryset(request)
|
||||||
return qs.prefetch_related('sublines').select_related('order')
|
return qs.prefetch_related('sublines').select_related('order')
|
||||||
|
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ class BillLineAdmin(admin.ModelAdmin):
|
||||||
display_total.admin_order_field = 'computed_total'
|
display_total.admin_order_field = 'computed_total'
|
||||||
|
|
||||||
def get_queryset(self, request):
|
def get_queryset(self, request):
|
||||||
qs = super(BillLineAdmin, self).get_queryset(request)
|
qs = super().get_queryset(request)
|
||||||
qs = qs.annotate(
|
qs = qs.annotate(
|
||||||
subline_total=Sum('sublines__total'),
|
subline_total=Sum('sublines__total'),
|
||||||
computed_total=(F('subtotal') + Sum(Coalesce('sublines__total', 0))) * (1+F('tax')/100),
|
computed_total=(F('subtotal') + Sum(Coalesce('sublines__total', 0))) * (1+F('tax')/100),
|
||||||
|
@ -151,7 +151,7 @@ class BillLineAdmin(admin.ModelAdmin):
|
||||||
|
|
||||||
class BillLineManagerAdmin(BillLineAdmin):
|
class BillLineManagerAdmin(BillLineAdmin):
|
||||||
def get_queryset(self, request):
|
def get_queryset(self, request):
|
||||||
qset = super(BillLineManagerAdmin, self).get_queryset(request)
|
qset = super().get_queryset(request)
|
||||||
if self.bill_ids:
|
if self.bill_ids:
|
||||||
return qset.filter(bill_id__in=self.bill_ids)
|
return qset.filter(bill_id__in=self.bill_ids)
|
||||||
return qset
|
return qset
|
||||||
|
@ -182,7 +182,7 @@ class BillLineManagerAdmin(BillLineAdmin):
|
||||||
'title': title,
|
'title': title,
|
||||||
}
|
}
|
||||||
context.update(extra_context or {})
|
context.update(extra_context or {})
|
||||||
return super(BillLineManagerAdmin, self).changelist_view(request, context)
|
return super().changelist_view(request, context)
|
||||||
|
|
||||||
|
|
||||||
class BillAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
class BillAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
|
@ -288,7 +288,7 @@ class BillAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
|
|
||||||
def get_urls(self):
|
def get_urls(self):
|
||||||
""" Hook bill lines management URLs on bill admin """
|
""" Hook bill lines management URLs on bill admin """
|
||||||
urls = super(BillAdmin, self).get_urls()
|
urls = super().get_urls()
|
||||||
admin_site = self.admin_site
|
admin_site = self.admin_site
|
||||||
extra_urls = [
|
extra_urls = [
|
||||||
url("^manage-lines/$",
|
url("^manage-lines/$",
|
||||||
|
@ -298,13 +298,13 @@ class BillAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
return extra_urls + urls
|
return extra_urls + urls
|
||||||
|
|
||||||
def get_readonly_fields(self, request, obj=None):
|
def get_readonly_fields(self, request, obj=None):
|
||||||
fields = super(BillAdmin, self).get_readonly_fields(request, obj)
|
fields = super().get_readonly_fields(request, obj)
|
||||||
if obj and not obj.is_open:
|
if obj and not obj.is_open:
|
||||||
fields += self.add_fields
|
fields += self.add_fields
|
||||||
return fields
|
return fields
|
||||||
|
|
||||||
def get_fieldsets(self, request, obj=None):
|
def get_fieldsets(self, request, obj=None):
|
||||||
fieldsets = super(BillAdmin, self).get_fieldsets(request, obj)
|
fieldsets = super().get_fieldsets(request, obj)
|
||||||
if obj:
|
if obj:
|
||||||
# Switches between amend_of_link and amend_links fields
|
# Switches between amend_of_link and amend_links fields
|
||||||
if obj.amend_of_id:
|
if obj.amend_of_id:
|
||||||
|
@ -316,7 +316,7 @@ class BillAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
return fieldsets
|
return fieldsets
|
||||||
|
|
||||||
def get_change_view_actions(self, obj=None):
|
def get_change_view_actions(self, obj=None):
|
||||||
actions = super(BillAdmin, self).get_change_view_actions(obj)
|
actions = super().get_change_view_actions(obj)
|
||||||
exclude = []
|
exclude = []
|
||||||
if obj:
|
if obj:
|
||||||
if not obj.is_open:
|
if not obj.is_open:
|
||||||
|
@ -326,7 +326,7 @@ class BillAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
return [action for action in actions if action.__name__ not in exclude]
|
return [action for action in actions if action.__name__ not in exclude]
|
||||||
|
|
||||||
def get_inline_instances(self, request, obj=None):
|
def get_inline_instances(self, request, obj=None):
|
||||||
inlines = super(BillAdmin, self).get_inline_instances(request, obj)
|
inlines = super().get_inline_instances(request, obj)
|
||||||
if obj and not obj.is_open:
|
if obj and not obj.is_open:
|
||||||
return [inline for inline in inlines if type(inline) != BillLineInline]
|
return [inline for inline in inlines if type(inline) != BillLineInline]
|
||||||
return [inline for inline in inlines if type(inline) != ClosedBillLineInline]
|
return [inline for inline in inlines if type(inline) != ClosedBillLineInline]
|
||||||
|
@ -337,13 +337,13 @@ class BillAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
kwargs['widget'] = forms.Textarea(attrs={'cols': 70, 'rows': 4})
|
kwargs['widget'] = forms.Textarea(attrs={'cols': 70, 'rows': 4})
|
||||||
elif db_field.name == 'html':
|
elif db_field.name == 'html':
|
||||||
kwargs['widget'] = forms.Textarea(attrs={'cols': 150, 'rows': 20})
|
kwargs['widget'] = forms.Textarea(attrs={'cols': 150, 'rows': 20})
|
||||||
formfield = super(BillAdmin, self).formfield_for_dbfield(db_field, **kwargs)
|
formfield = super().formfield_for_dbfield(db_field, **kwargs)
|
||||||
if db_field.name == 'amend_of':
|
if db_field.name == 'amend_of':
|
||||||
formfield.queryset = formfield.queryset.filter(is_open=False)
|
formfield.queryset = formfield.queryset.filter(is_open=False)
|
||||||
return formfield
|
return formfield
|
||||||
|
|
||||||
def get_queryset(self, request):
|
def get_queryset(self, request):
|
||||||
qs = super(BillAdmin, self).get_queryset(request)
|
qs = super().get_queryset(request)
|
||||||
qs = qs.annotate(
|
qs = qs.annotate(
|
||||||
models.Count('lines'),
|
models.Count('lines'),
|
||||||
# FIXME https://code.djangoproject.com/ticket/10060
|
# FIXME https://code.djangoproject.com/ticket/10060
|
||||||
|
@ -360,7 +360,7 @@ class BillAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
# TODO raise404, here and everywhere
|
# TODO raise404, here and everywhere
|
||||||
bill = self.get_object(request, unquote(object_id))
|
bill = self.get_object(request, unquote(object_id))
|
||||||
actions.validate_contact(request, bill, error=False)
|
actions.validate_contact(request, bill, error=False)
|
||||||
return super(BillAdmin, self).change_view(request, object_id, **kwargs)
|
return super().change_view(request, object_id, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
admin.site.register(Bill, BillAdmin)
|
admin.site.register(Bill, BillAdmin)
|
||||||
|
@ -384,7 +384,7 @@ class BillContactInline(admin.StackedInline):
|
||||||
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(BillContactInline, self).formfield_for_dbfield(db_field, **kwargs)
|
return super().formfield_for_dbfield(db_field, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
def has_bill_contact(account):
|
def has_bill_contact(account):
|
||||||
|
|
|
@ -404,7 +404,8 @@ class BillLine(models.Model):
|
||||||
start_on = models.DateField(_("start"))
|
start_on = models.DateField(_("start"))
|
||||||
end_on = models.DateField(_("end"), null=True, blank=True)
|
end_on = models.DateField(_("end"), null=True, blank=True)
|
||||||
order = models.ForeignKey(settings.BILLS_ORDER_MODEL, null=True, blank=True,
|
order = models.ForeignKey(settings.BILLS_ORDER_MODEL, null=True, blank=True,
|
||||||
help_text=_("Informative link back to the order"), on_delete=models.SET_NULL)
|
related_name='lines', on_delete=models.SET_NULL,
|
||||||
|
help_text=_("Informative link back to the order"))
|
||||||
order_billed_on = models.DateField(_("order billed"), null=True, blank=True)
|
order_billed_on = models.DateField(_("order billed"), null=True, blank=True)
|
||||||
order_billed_until = models.DateField(_("order billed until"), null=True, blank=True)
|
order_billed_until = models.DateField(_("order billed until"), null=True, blank=True)
|
||||||
created_on = models.DateField(_("created"), auto_now_add=True)
|
created_on = models.DateField(_("created"), auto_now_add=True)
|
||||||
|
|
|
@ -104,6 +104,9 @@ class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
fieldsets += (
|
fieldsets += (
|
||||||
(_("SOA"), {
|
(_("SOA"), {
|
||||||
'classes': ('collapse',),
|
'classes': ('collapse',),
|
||||||
|
'description': _(
|
||||||
|
"SOA (Start of Authority) records are used to determine how your "
|
||||||
|
"zone propagates to the secondary nameservers."),
|
||||||
'fields': ('serial', 'refresh', 'retry', 'expire', 'min_ttl'),
|
'fields': ('serial', 'refresh', 'retry', 'expire', 'min_ttl'),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
|
@ -10,6 +10,7 @@ from orchestra.contrib.accounts.actions import list_accounts
|
||||||
from orchestra.contrib.accounts.admin import SelectAccountAdminMixin
|
from orchestra.contrib.accounts.admin import SelectAccountAdminMixin
|
||||||
from orchestra.contrib.accounts.filters import IsActiveListFilter
|
from orchestra.contrib.accounts.filters import IsActiveListFilter
|
||||||
|
|
||||||
|
from . import settings
|
||||||
from .forms import ListCreationForm, ListChangeForm
|
from .forms import ListCreationForm, ListChangeForm
|
||||||
from .models import List
|
from .models import List
|
||||||
|
|
||||||
|
@ -39,6 +40,8 @@ class ListAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedModel
|
||||||
}),
|
}),
|
||||||
(_("Address"), {
|
(_("Address"), {
|
||||||
'classes': ('wide',),
|
'classes': ('wide',),
|
||||||
|
'description': _("Additional address besides the default <name>@%s"
|
||||||
|
) % settings.LISTS_DEFAULT_DOMAIN,
|
||||||
'fields': (('address_name', 'address_domain'),)
|
'fields': (('address_name', 'address_domain'),)
|
||||||
}),
|
}),
|
||||||
(_("Admin"), {
|
(_("Admin"), {
|
||||||
|
|
|
@ -49,6 +49,8 @@ class MailboxAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedMo
|
||||||
}),
|
}),
|
||||||
(_("Custom filtering"), {
|
(_("Custom filtering"), {
|
||||||
'classes': ('collapse',),
|
'classes': ('collapse',),
|
||||||
|
'description': _("Please remember to select <tt>custom filtering</tt> "
|
||||||
|
"if you want this filter to be applied."),
|
||||||
'fields': ('custom_filtering',),
|
'fields': ('custom_filtering',),
|
||||||
}),
|
}),
|
||||||
(_("Addresses"), {
|
(_("Addresses"), {
|
||||||
|
|
|
@ -78,16 +78,16 @@ class Command(BaseCommand):
|
||||||
for instance in queryset:
|
for instance in queryset:
|
||||||
manager.collect(instance, action, operations=operations, route_cache=route_cache)
|
manager.collect(instance, action, operations=operations, route_cache=route_cache)
|
||||||
scripts, serialize = manager.generate(operations)
|
scripts, serialize = manager.generate(operations)
|
||||||
servers = []
|
servers = set()
|
||||||
# Print scripts
|
# Print scripts
|
||||||
for key, value in scripts.items():
|
for key, value in scripts.items():
|
||||||
route, __, __ = key
|
route, __, __ = key
|
||||||
backend, operations = value
|
backend, operations = value
|
||||||
servers.append(str(route.host))
|
servers.add(str(route.host))
|
||||||
self.stdout.write('# Execute %s on %s' % (backend.get_name(), route.host))
|
self.stdout.write('# Execute %s on %s' % (backend.get_name(), route.host))
|
||||||
for method, commands in backend.scripts:
|
for method, commands in backend.scripts:
|
||||||
script = '\n'.join(commands)
|
script = '\n'.join(commands)
|
||||||
self.stdout.write(script)
|
self.stdout.write(script.encode('ascii', errors='replace').decode())
|
||||||
if interactive:
|
if interactive:
|
||||||
context = {
|
context = {
|
||||||
'servers': ', '.join(servers),
|
'servers': ', '.join(servers),
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
from django import forms
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.core.urlresolvers import reverse, NoReverseMatch
|
from django.core.urlresolvers import reverse, NoReverseMatch
|
||||||
from django.db.models import Prefetch
|
from django.db.models import Prefetch
|
||||||
|
@ -38,8 +39,9 @@ class MetricStorageInline(admin.TabularInline):
|
||||||
change_view = bool(self.parent_object and self.parent_object.pk)
|
change_view = bool(self.parent_object and self.parent_object.pk)
|
||||||
if change_view:
|
if change_view:
|
||||||
qs = qs.order_by('-id')
|
qs = qs.order_by('-id')
|
||||||
|
parent_id = self.parent_object.pk
|
||||||
try:
|
try:
|
||||||
tenth_id = qs.filter(order_id=self.parent_object.pk).values_list('id', flat=True)[9]
|
tenth_id = qs.filter(order_id=parent_id).values_list('id', flat=True)[9]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
|
@ -72,7 +74,37 @@ class OrderAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
Prefetch('metrics', queryset=MetricStorage.objects.order_by('-id')),
|
Prefetch('metrics', queryset=MetricStorage.objects.order_by('-id')),
|
||||||
)
|
)
|
||||||
list_select_related = ('account', 'service')
|
list_select_related = ('account', 'service')
|
||||||
readonly_fields = ('content_object_repr', 'content_object_link')
|
add_fieldsets = (
|
||||||
|
(None, {
|
||||||
|
'fields': ('account', 'service')
|
||||||
|
}),
|
||||||
|
(_("Object"), {
|
||||||
|
'fields': ('content_type', 'object_id',),
|
||||||
|
}),
|
||||||
|
(_("State"), {
|
||||||
|
'fields': ('registered_on', 'cancelled_on', 'billed_on', 'billed_metric',
|
||||||
|
'billed_until' )
|
||||||
|
}),
|
||||||
|
(None, {
|
||||||
|
'fields': ('description', 'ignore',),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
fieldsets = (
|
||||||
|
(None, {
|
||||||
|
'fields': ('account_link', 'service_link', 'content_object_link'),
|
||||||
|
}),
|
||||||
|
(_("State"), {
|
||||||
|
'fields': ('registered_on', 'cancelled_on', 'billed_on', 'billed_metric',
|
||||||
|
'billed_until' )
|
||||||
|
}),
|
||||||
|
(None, {
|
||||||
|
'fields': ('description', 'ignore', 'bills_links'),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
readonly_fields = (
|
||||||
|
'content_object_repr', 'content_object_link', 'bills_links', 'account_link',
|
||||||
|
'service_link'
|
||||||
|
)
|
||||||
|
|
||||||
service_link = admin_link('service')
|
service_link = admin_link('service')
|
||||||
display_registered_on = admin_date('registered_on')
|
display_registered_on = admin_date('registered_on')
|
||||||
|
@ -99,6 +131,15 @@ class OrderAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
content_object_link.allow_tags = True
|
content_object_link.allow_tags = True
|
||||||
content_object_link.admin_order_field = 'content_object_repr'
|
content_object_link.admin_order_field = 'content_object_repr'
|
||||||
|
|
||||||
|
def bills_links(self, order):
|
||||||
|
bills = []
|
||||||
|
make_link = admin_link()
|
||||||
|
for line in order.lines.select_related('bill').distinct('bill'):
|
||||||
|
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):
|
def display_billed_until(self, order):
|
||||||
billed_until = order.billed_until
|
billed_until = order.billed_until
|
||||||
red = False
|
red = False
|
||||||
|
@ -133,6 +174,12 @@ class OrderAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
return metric.value
|
return metric.value
|
||||||
display_metric.short_description = _("Metric")
|
display_metric.short_description = _("Metric")
|
||||||
|
|
||||||
|
def formfield_for_dbfield(self, db_field, **kwargs):
|
||||||
|
""" Make value input widget bigger """
|
||||||
|
if db_field.name == 'description':
|
||||||
|
kwargs['widget'] = forms.Textarea(attrs={'cols': 70, 'rows': 2})
|
||||||
|
return super().formfield_for_dbfield(db_field, **kwargs)
|
||||||
|
|
||||||
# def get_changelist(self, request, **kwargs):
|
# def get_changelist(self, request, **kwargs):
|
||||||
# ChangeList = super(OrderAdmin, self).get_changelist(request, **kwargs)
|
# ChangeList = super(OrderAdmin, self).get_changelist(request, **kwargs)
|
||||||
# class OrderFilterChangeList(ChangeList):
|
# class OrderFilterChangeList(ChangeList):
|
||||||
|
|
|
@ -54,6 +54,10 @@ class TransactionInline(admin.TabularInline):
|
||||||
def has_add_permission(self, *args, **kwargs):
|
def has_add_permission(self, *args, **kwargs):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def get_queryset(self, *args, **kwargs):
|
||||||
|
qs = super().get_queryset(*args, **kwargs)
|
||||||
|
return qs.select_related('source', 'bill')
|
||||||
|
|
||||||
|
|
||||||
class TransactionAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
class TransactionAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
||||||
list_display = (
|
list_display = (
|
||||||
|
|
Loading…
Reference in New Issue