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

如何使用Django ORM实现左连接/连表查询,附模型和原生SQL参考

问题1:原生SQL语句是否正确

如果你的业务需求是查询用户asdffdsa提交的、处理状态为已完成的广告申请对应的所有广告主发布记录+申请记录,这条SQL的语法逻辑是正确的,但是有两个需要注意的细节:

  • 你模型中Ad_company_apply.is_done定义为CharField类型,若数据库中该字段存储的是字符格式的'1',SQL语句中is_done = 1需要改成is_done = '1',否则可能出现隐式类型转换导致查询结果为空
  • SELECT *会返回两个表的所有字段,若两张表存在同名字段(比如两张表都有idx、is_done字段),后续取数时会出现字段覆盖的问题,建议按需指定查询字段

问题2:如何用ORM实现左连接等连表查询逻辑

你当前无法用ORM做连表查询的核心原因是没有在两个模型中定义关联关系,有两种实现方式:

方案1:新增外键关联(推荐,不影响现有表结构)

因为你模型Meta中设置了managed = False,修改模型新增外键不会触发表结构变更,只要把Ad_company_apply中的parent_idx字段修改为外键即可:

class Ad_company_apply(models.Model):
    idx = models.AutoField(primary_key=True)
    # 把原来的parent_idx = models.IntegerField()替换成下面的外键定义
    parent = models.ForeignKey(
        Ad_company,
        on_delete=models.DO_NOTHING,
        db_column='parent_idx', # 对应数据库表的实际字段名
        related_name='applies'
    )
    # 其余字段保持不变

修改后就可以直接用ORM做各种关联查询:

  • 你需要的内连接查询实现:
# 结果是符合条件的Ad_company对象,可直接通过.apply访问关联的申请记录
queryset = Ad_company.objects.filter(
    applies__is_done='1',
    applies__username='asdffdsa'
).select_related('applies')
  • 左连接查询实现(保留所有Ad_company记录,即使没有对应的申请记录):
from django.db.models import Prefetch
queryset = Ad_company.objects.all().prefetch_related(
    Prefetch('applies', queryset=Ad_company_apply.objects.filter(is_done='1', username='asdffdsa'))
)

方案2:不修改现有模型的实现

如果不能修改模型定义,可以用子查询或者raw方法实现:

# 子查询方式实现需求
apply_ids = Ad_company_apply.objects.filter(
    is_done='1',
    username='asdffdsa'
).values_list('parent_idx', flat=True)
queryset = Ad_company.objects.filter(idx__in=apply_ids)

# 直接执行原生SQL的方式
queryset = Ad_company.objects.raw("""
    SELECT ad_write_company.* FROM ad_write_company 
    INNER JOIN ad_write_company_apply ON ad_write_company.idx = ad_write_company_apply.parent_idx 
    where ad_write_company_apply.is_done = %s and ad_write_company_apply.username = %s
""", params=['1', 'asdffdsa'])

问题3:是否有其他更优的实现方案

最优方案就是前面提到的新增外键关联的方式,优势如下:

  • 完全不影响现有数据库结构,仅修改Django模型的逻辑关联定义
  • 后续所有关联查询都可以直接用ORM的语法实现,不需要手写原生SQL,代码可读性和可维护性更高
  • 可以利用ORM的查询优化特性(比如select_related、prefetch_related)控制连表查询的性能,避免N+1查询问题

如果业务逻辑非常简单,后续也不会有其他关联查询的需求,直接用raw方法执行你写的原生SQL也是完全可行的,注意用params传参避免SQL注入风险即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 14:15:06