You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django中如何返回筛选地址全部交易历史?优化查询代码

房产交易历史查询代码优化方案

问题背景

现有Django查询代码通过列表推导返回符合条件房产的全部交易历史,但列表会一次性加载所有数据到内存,需要优化为无需生成列表即可返回全部交易历史,同时保留原有功能。

优化方案

方案一:生成器替代列表推导(改动最小)

将原代码中返回列表的部分改为生成器表达式,这样不会一次性生成所有元素,而是按需迭代,大幅降低内存占用,调用方的extend操作可正常使用。

修改后返回部分代码:

return (
    [
        e.id,
        e.bedrooms,
        e.type,
        e.year_built,
        e.square_feet,
        e.lot_size,
        e.location.id,
        e.location.address,
        e.location.postal_code,
        e.location.latitude,
        e.location.longitude,
        e.location.city.name if e.location.city else None,
        e.location.neighbourhood.name if e.location.neighbourhood else None,
        sh.date,
        sh.price
    ]
    for e in estates
    for sh in e.sold_histories.all()
)

方案二:直接关联查询(性能最优)

通过SoldHistory模型直接关联查询所需字段,使用values_list返回惰性求值的QuerySet,无需加载ORM实例,内存占用极低,查询效率更高。

完整优化后代码:

def filter_model(estate, years=[], exact_match=False, distance_km=None):
    query_filter = Q(location__postal_code__isnull=False, sold_histories__isnull=False)

    if distance_km:
        query_filter &= Q(location__point__distance_lte=(
            estate.location.point, distance_km))
        query_filter &= Q(type=estate.type)
        query_filter &= Q(square_feet__isnull=False)
        query_filter &= Q(year_built__isnull=False)
        if estate.type == 2:
            address = str(estate.location.address).split('#')[0].strip()
            query_filter &= Q(location__address__icontains=address)

        # 获取符合条件的房产ID集合
        estate_ids = Estate.objects.filter(query_filter).values_list('id', flat=True).distinct()
        # 直接查询关联的交易历史,返回所需字段
        return SoldHistory.objects.filter(
            estate_id__in=estate_ids
        ).select_related(
            'estate__location__city',
            'estate__location__neighbourhood'
        ).order_by('-date').values_list(
            'estate__id',
            'estate__bedrooms',
            'estate__type',
            'estate__year_built',
            'estate__square_feet',
            'estate__lot_size',
            'estate__location__id',
            'estate__location__address',
            'estate__location__postal_code',
            'estate__location__latitude',
            'estate__location__longitude',
            'estate__location__city__name',
            'estate__location__neighbourhood__name',
            'date',
            'price'
        )
    else:
        if len(years) == 2:
            query_filter &= Q(sold_histories__date__year=years[0])

        if exact_match:
            query_filter &= Q(location__city__province__id=estate.location.city.province.id)
        else:
            query_filter &= Q(location__city__id=estate.location.city.id)

        # 获取符合条件的房产ID集合
        estate_ids = Estate.objects.filter(query_filter).filter(
            sold_histories__date__year=years[1]
        ).values_list('id', flat=True).distinct()
        # 查询指定年份的交易历史,返回所需字段
        return SoldHistory.objects.filter(
            estate_id__in=estate_ids,
            date__year__in=years
        ).select_related(
            'estate__location__city',
            'estate__location__neighbourhood'
        ).values_list(
            'estate__id',
            'estate__bedrooms',
            'estate__type',
            'estate__year_built',
            'estate__square_feet',
            'estate__lot_size',
            'estate__location__id',
            'estate__location__address',
            'estate__location__postal_code',
            'estate__location__latitude',
            'estate__location__longitude',
            'estate__location__city__name',
            'estate__location__neighbourhood__name',
            'date',
            'price'
        )

说明

  • 方案一仅需修改返回部分,保留原有ORM实例逻辑,适合需要后续操作对象的场景。
  • 方案二直接从数据库获取目标字段,避免加载冗余数据,性能更优,适合大数据量场景。
  • 两种方案返回的结果均可直接用于estates_by_km.extend(...),无需修改调用逻辑。

内容的提问来源于stack exchange,提问作者user9272398

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 11:38:11