Как уменьшить количество повторяющихся SQL-запросов в django admin - PullRequest
0 голосов
/ 15 февраля 2019

У меня есть model, который является ForeginKey для ряда других моделей.Я определил их как TabularInline в пределах моего ModelAdmin.Выглядит это так:

class HouseAdmin(admin.ModelAdmin):
    list_display = ['owner', 'get_house','number','street','city']
    list_filter = ['completed']
    readonly_fields = ['slug']
    inlines = [HouseWorkInline, HouseDocumentInline, HouseBudgetInline, HouseSelectionInline, \
        HouseSpecificationInline]
    actions = [send_schedule_emails]
    fieldsets = (
        (None, {'fields' : ('owner', 'number','street', 'city', 'start_date','completed')}),
    )
    search_fields = ['street','number','owner__username','city']

Выполняется 764 запроса, в том числе 757 похожих и 468 дубликатов.Я пытаюсь понять, как уменьшить это, используя select_related, но ничего, что я делаю, кажется, не имеет никакого значения.

Может кто-нибудь дать мне несколько советов, пожалуйста.Спасибо

** РЕДАКТИРОВАТЬ ** Добавленные строки

class HouseSpecificationInline(admin.TabularInline):
    readonly_fields = ['get_specification']
    fields = ['get_specification','notes','order',]
    model = HouseSpecification
    extra = 0
    template = 'admin/houses/housespecification/edit_inline/tabular.html'

    def get_specification(self, obj):
        return mark_safe('%s' % (obj.specification))
    get_specification.short_description = 'Specification'

class HouseSelectionInline(admin.TabularInline):
    readonly_fields = ['get_selection','get_notes','get_external_link']
    fields = ['get_selection','get_notes','get_external_link','notes',]
    model = HouseSelection
    extra = 0
    can_order = True
    template = 'admin/houses/housework/edit_inline/tabular.html'

    def has_add_permission(self, request):
        return False

    def get_selection(self, obj):
        if obj.selection.f:
            return mark_safe('<a href="/core/download-pdf/%s">%s</a>' % (obj.selection.id, obj.selection))
        else :
            return mark_safe('%s' % (obj.selection))
    get_selection.short_description = 'Selection'

    def get_notes(self, obj):
        return obj.selection.notes

    def get_external_link(self, obj):
        if obj.selection.external_link:
            return mark_safe('<a target="_blank" href="%s">%s</a>' % (obj.selection.external_link, obj.selection.external_link))
        else: return ''
    get_external_link.short_description = "External Link"

class HouseBudgetInline(admin.TabularInline):
    model = HouseBudget
    extra = 1
    can_order = True
    show_change_link = True
    template = 'admin/houses/housebudget/edit_inline/tabular.html'

class HouseWorkInline(admin.TabularInline):
    readonly_fields =['activity','start_date','punches', 'get_delay']
    fields = ['activity','start_date','length','get_delay','note','contractor','date_completed','punches']
    model = HouseWork
    extra = 0
    can_delete = False
    show_change_link = True
    template = 'admin/houses/housework/edit_inline/tabular.html'

    def has_add_permission(self, request):
        return False

    def get_delay(self, obj):
        return obj.delay
    get_delay.short_description = 'Delay'        

    def punches(self, obj):
        text = ''
        for punch in obj.punch_set.filter(completed=False):
            text += punch.date_created.strftime("%m/%d/%Y") + ' - ' + punch.notes + '<br />'
        return mark_safe(text)
    punches.short_description = 'Punch List'

1 Ответ

0 голосов
/ 15 февраля 2019

Вы не показали пример ваших дублирующих запросов.Тем не менее, я вижу, что ваш список HouseSelectionInline отображает информацию о связанном объекте selection.Вы должны переопределить get_queryset, чтобы использовать select_related, чтобы получить эту связь в исходном запросе:

class HouseSelectionInline(admin.TabularInline):
    ...
    def get_queryset(self, request):
        qs = super().get_queryset(request)
        return qs.select_related('selection')

Аналогично, для HouseWork вы должны использовать prefetch_related, чтобы получить данные для punches, потому чтоэто обратная связь:

class HouseWorkInline(admin.TabularInline):
    ...
    def get_queryset(self, request):
        qs = super().get_queryset(request)
        punch_query = Punch.objects.filter(completed=False)
        incomplete_punches = Prefetch('punch_set', punch_query, to_attr='incomplete_punches')
        return qs.prefetch_related(incomplete_punches)

    def punches(self, obj):
        text = ''
        for punch in obj.incomplete_punches:
            text += punch.date_created.strftime("%m/%d/%Y") + ' - ' + punch.notes + '<br />'
        return mark_safe(text)
    punches.short_description = 'Punch List'

Я не вижу, что такое HouseSpecification.specification и HouseWork.delay, но если они также FK, вы должны сделать что-то подобное.

...