Improved admin performance

This commit is contained in:
Marc Aymerich 2016-02-23 11:49:10 +00:00
parent e388346f9a
commit 201608c49c
9 changed files with 81 additions and 31 deletions

12
TODO.md
View file

@ -435,7 +435,7 @@ mkhomedir_helper or create ssh homes with bash.rc and such
# 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:
shit_happend, otherwise schedule for first query
# 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
# mailscanner phishing, spam, whitelist choices
# show base and total desglosed
# Reverse lOgHistory order by date (lastest first)
* setuppostgres use porject_name for db name and user instead of orchestra
# POSTFIX web traffic monitor '": uid=" from=<%(user)s>'
# 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
# INDEXES for most used queries: account FK

View file

@ -64,10 +64,10 @@ class BillLineInline(admin.TabularInline):
kwargs['widget'] = forms.TextInput(attrs={'size':'50'})
elif db_field.name not in ('start_on', 'end_on'):
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):
qs = super(BillLineInline, self).get_queryset(request)
qs = super().get_queryset(request)
return qs.prefetch_related('sublines').select_related('order')
@ -141,7 +141,7 @@ class BillLineAdmin(admin.ModelAdmin):
display_total.admin_order_field = 'computed_total'
def get_queryset(self, request):
qs = super(BillLineAdmin, self).get_queryset(request)
qs = super().get_queryset(request)
qs = qs.annotate(
subline_total=Sum('sublines__total'),
computed_total=(F('subtotal') + Sum(Coalesce('sublines__total', 0))) * (1+F('tax')/100),
@ -151,7 +151,7 @@ class BillLineAdmin(admin.ModelAdmin):
class BillLineManagerAdmin(BillLineAdmin):
def get_queryset(self, request):
qset = super(BillLineManagerAdmin, self).get_queryset(request)
qset = super().get_queryset(request)
if self.bill_ids:
return qset.filter(bill_id__in=self.bill_ids)
return qset
@ -182,7 +182,7 @@ class BillLineManagerAdmin(BillLineAdmin):
'title': title,
}
context.update(extra_context or {})
return super(BillLineManagerAdmin, self).changelist_view(request, context)
return super().changelist_view(request, context)
class BillAdmin(AccountAdminMixin, ExtendedModelAdmin):
@ -288,7 +288,7 @@ class BillAdmin(AccountAdminMixin, ExtendedModelAdmin):
def get_urls(self):
""" Hook bill lines management URLs on bill admin """
urls = super(BillAdmin, self).get_urls()
urls = super().get_urls()
admin_site = self.admin_site
extra_urls = [
url("^manage-lines/$",
@ -298,13 +298,13 @@ class BillAdmin(AccountAdminMixin, ExtendedModelAdmin):
return extra_urls + urls
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:
fields += self.add_fields
return fields
def get_fieldsets(self, request, obj=None):
fieldsets = super(BillAdmin, self).get_fieldsets(request, obj)
fieldsets = super().get_fieldsets(request, obj)
if obj:
# Switches between amend_of_link and amend_links fields
if obj.amend_of_id:
@ -316,7 +316,7 @@ class BillAdmin(AccountAdminMixin, ExtendedModelAdmin):
return fieldsets
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 = []
if obj:
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]
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:
return [inline for inline in inlines if type(inline) != BillLineInline]
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})
elif db_field.name == 'html':
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':
formfield.queryset = formfield.queryset.filter(is_open=False)
return formfield
def get_queryset(self, request):
qs = super(BillAdmin, self).get_queryset(request)
qs = super().get_queryset(request)
qs = qs.annotate(
models.Count('lines'),
# FIXME https://code.djangoproject.com/ticket/10060
@ -360,7 +360,7 @@ class BillAdmin(AccountAdminMixin, ExtendedModelAdmin):
# TODO raise404, here and everywhere
bill = self.get_object(request, unquote(object_id))
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)
@ -384,7 +384,7 @@ class BillContactInline(admin.StackedInline):
kwargs['widget'] = forms.Textarea(attrs={'cols': 70, 'rows': 2})
if db_field.name == 'email_usage':
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):

View file

@ -404,7 +404,8 @@ class BillLine(models.Model):
start_on = models.DateField(_("start"))
end_on = models.DateField(_("end"), 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_until = models.DateField(_("order billed until"), null=True, blank=True)
created_on = models.DateField(_("created"), auto_now_add=True)

View file

@ -104,6 +104,9 @@ class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin):
fieldsets += (
(_("SOA"), {
'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'),
}),
)

View file

@ -10,6 +10,7 @@ from orchestra.contrib.accounts.actions import list_accounts
from orchestra.contrib.accounts.admin import SelectAccountAdminMixin
from orchestra.contrib.accounts.filters import IsActiveListFilter
from . import settings
from .forms import ListCreationForm, ListChangeForm
from .models import List
@ -39,6 +40,8 @@ class ListAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedModel
}),
(_("Address"), {
'classes': ('wide',),
'description': _("Additional address besides the default &lt;name&gt;@%s"
) % settings.LISTS_DEFAULT_DOMAIN,
'fields': (('address_name', 'address_domain'),)
}),
(_("Admin"), {

View file

@ -49,6 +49,8 @@ class MailboxAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedMo
}),
(_("Custom filtering"), {
'classes': ('collapse',),
'description': _("Please remember to select <tt>custom filtering</tt> "
"if you want this filter to be applied."),
'fields': ('custom_filtering',),
}),
(_("Addresses"), {

View file

@ -78,16 +78,16 @@ class Command(BaseCommand):
for instance in queryset:
manager.collect(instance, action, operations=operations, route_cache=route_cache)
scripts, serialize = manager.generate(operations)
servers = []
servers = set()
# Print scripts
for key, value in scripts.items():
route, __, __ = key
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))
for method, commands in backend.scripts:
script = '\n'.join(commands)
self.stdout.write(script)
self.stdout.write(script.encode('ascii', errors='replace').decode())
if interactive:
context = {
'servers': ', '.join(servers),

View file

@ -1,3 +1,4 @@
from django import forms
from django.contrib import admin
from django.core.urlresolvers import reverse, NoReverseMatch
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)
if change_view:
qs = qs.order_by('-id')
parent_id = self.parent_object.pk
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:
pass
else:
@ -72,7 +74,37 @@ class OrderAdmin(AccountAdminMixin, ExtendedModelAdmin):
Prefetch('metrics', queryset=MetricStorage.objects.order_by('-id')),
)
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')
display_registered_on = admin_date('registered_on')
@ -99,6 +131,15 @@ class OrderAdmin(AccountAdminMixin, ExtendedModelAdmin):
content_object_link.allow_tags = True
content_object_link.admin_order_field = 'content_object_repr'
def bills_links(self, order):
bills = []
make_link = admin_link()
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):
billed_until = order.billed_until
red = False
@ -133,6 +174,12 @@ class OrderAdmin(AccountAdminMixin, ExtendedModelAdmin):
return metric.value
display_metric.short_description = _("Metric")
def formfield_for_dbfield(self, db_field, **kwargs):
""" Make value input widget bigger """
if db_field.name == 'description':
kwargs['widget'] = forms.Textarea(attrs={'cols': 70, 'rows': 2})
return super().formfield_for_dbfield(db_field, **kwargs)
# def get_changelist(self, request, **kwargs):
# ChangeList = super(OrderAdmin, self).get_changelist(request, **kwargs)
# class OrderFilterChangeList(ChangeList):

View file

@ -54,6 +54,10 @@ class TransactionInline(admin.TabularInline):
def has_add_permission(self, *args, **kwargs):
return False
def get_queryset(self, *args, **kwargs):
qs = super().get_queryset(*args, **kwargs)
return qs.select_related('source', 'bill')
class TransactionAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
list_display = (