如何减少django admin中重复的sql查询

如何减少django admin中重复的sql查询,django,django-admin,Django,Django Admin,我有一个模型,它是许多其他模型的前身。在我的ModelAdmin中,我将它们定义为tablerinlines。看起来是这样的: class HouseAdmin(admin.ModelAdmin): list_display = ['owner', 'get_house','number','street','city'] list_filter = ['completed'] readonly_fields = ['slug'] inlines = [House

我有一个
模型
,它是许多其他模型的前身。在我的
ModelAdmin
中,我将它们定义为
tablerinline
s。看起来是这样的:

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\u 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'
class House SpecificationInline(管理员列表行):
只读_字段=['get_specification']
字段=['get_specification'、'notes'、'order'、]
型号=规格
额外=0
模板='admin/houses/housespecification/edit_inline/tabular.html'
def get_规格(自身、obj):
返回标记_safe(“%s%”(对象规范))
get_specification.short_description='specification'
类别House SelectionLine(管理员列表行):
只读_字段=['get_selection'、'get_notes'、'get_external_link']
字段=['get_selection'、'get_notes'、'get_external_link'、'notes'、]
模型=房屋选择
额外=0
可以吗
模板='admin/houses/housedwork/edit_inline/tabular.html'
def具有添加权限(自我、请求):
返回错误
def get_选择(自身、obj):
如果对象选择.f:
返回标记_安全(“”%(对象选择id,对象选择))
其他:
返回标记_safe(“%s%”(对象选择))
get_selection.short_description='selection'
def get_注释(自身、obj):
返回obj.selection.notes
def get_外部链接(自身、obj):
如果obj.selection.external_链接:
返回标记安全(“”%(对象选择.外部链接,对象选择.外部链接))
其他:返回“”
获取外部链接。short\u description=“外部链接”
类House BudgetLine(管理员列表行):
模型=房屋预算
额外=1
可以吗
显示更改链接=真
模板='admin/houses/housebutch/edit_inline/tabular.html'
类HouseWorkInline(管理列表行):
只读字段=['activity'、'start\u date'、'Punchs'、'get\u delay']
字段=['activity'、'start\u date'、'length'、'get\u delay'、'note'、'contractor'、'date\u completed'、'Punchs']
模特=家务
额外=0
can_delete=False
显示更改链接=真
模板='admin/houses/housedwork/edit_inline/tabular.html'
def具有添加权限(自我、请求):
返回错误
def获取延迟(自身、obj):
返回对象延迟
get_delay.short_description='delay'
def冲头(自身、obj):
文本=“”
对于打孔对象打孔设置过滤器(完成=错误):
text+=punch.date_created.strftime(“%m/%d/%Y”)++'-'+punch.notes++'
返回标记_安全(文本) punchs.short_description='打孔列表'
您没有显示重复查询的示例。但是,我可以看到您的House SelectionLine列表正在显示相关的
选择
对象的信息。您应该覆盖
get\u queryset
以使用
select\u related
在原始查询中获取该关系:

class HouseSelectionInline(admin.TabularInline):
    ...
    def get_queryset(self, request):
        qs = super().get_queryset(request)
        return qs.select_related('selection')
同样,对于家务活,您应该使用
prefetch\u related
获取
打孔的数据,因为这是一种反向关系:

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'
class HouseWorkInline(管理列表行):
...
def get_queryset(自我,请求):
qs=super().get_queryset(请求)
punch\u query=punch.objects.filter(completed=False)
不完整的穿孔=预取('punch\u set',punch\u query,to\u attr='complete\u punchs')
返回qs.预回迁相关(未完成打孔)
def冲头(自身、obj):
文本=“”
对于打孔对象,不完整的打孔:
text+=punch.date_created.strftime(“%m/%d/%Y”)++'-'+punch.notes++'
返回标记_安全(文本) punchs.short_description='打孔列表'

我看不出
HouseSpecification.specification
household.delay
是什么,但如果它们也是FKs,你应该做类似的事情。

你需要显示这些内联线,以及重复查询的示例谢谢Daniel。这应该是
punchs
而不是
selection
用于
houseOrkInline
?我刚刚尝试为
HouseSelectionInline
添加
get\u queryset()
,它给出了以下错误:
get\u queryset()取1个位置参数,但给出2个
,实际上我意识到打孔要复杂一些,因为在完成时进行过滤-所以需要自定义预取对象。请参阅我的更新(它还修复了
get_queryset
参数)。我已将建议的更改应用于所有外键,并取得了重大进展,但我仍然收到280次这样的查询:
SELECT••FROM“houses_house”其中的“houses_house”。“id”=12
Hmm,这似乎是父房屋模型本身的FK。尝试将
'house'
添加到所有
select\u相关的
呼叫中。