Python/Django新手求助:如何用Django ORM实现多表数据查询
Django ORM 关联表查询指南(针对你的三张表)
嘿,作为Python和Django的新手,刚接触ORM时面对关联表确实容易犯难——别担心,我结合你的三张表结构,一步步给你讲清楚怎么用ORM获取数据!
第一步:先确认你的Django模型定义
首先得确保你的模型(models.py)正确映射了数据库表,外键关联要对应好,这是ORM查询的基础:
from django.db import models class User(models.Model): id = models.AutoField(primary_key=True) name = models.CharField(max_length=100) class Meta: db_table = 'USER' # 匹配你数据库的大写表名 class InvestmentName(models.Model): id = models.AutoField(primary_key=True) name = models.CharField(max_length=100) class Meta: db_table = 'INVESTMENT_NAME' class Wallet(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE, db_column='user_id') investment = models.ForeignKey(InvestmentName, on_delete=models.CASCADE, db_column='inv_id') date = models.DateField() quantity = models.DecimalField(max_digits=10, decimal_places=2) amount = models.DecimalField(max_digits=12, decimal_places=2) # 注意:数据库里的"current price"有空格,这里用db_column指定对应字段 current_price = models.DecimalField(max_digits=10, decimal_places=2, db_column='current price') class Meta: db_table = 'WALLET'
小提醒:数据库字段带空格其实不太规范,后续如果有机会,建议改成
current_price这类下划线命名,能减少很多不必要的麻烦。
第二步:常见查询场景示例
下面是你可能用到的几种查询需求,直接拿代码用就行:
1. 获取某个用户的所有钱包记录,同时显示对应的投资名称
比如要找id为1的用户的所有投资记录:
# 先获取目标用户 user = User.objects.get(id=1) # 用select_related预加载关联的投资名称,避免多次查询数据库 wallet_records = Wallet.objects.filter(user=user).select_related('investment') # 遍历输出详情 for record in wallet_records: print(f"用户名: {user.name}") print(f"投资产品: {record.investment.name}") print(f"日期: {record.date}, 数量: {record.quantity}, 投入金额: {record.amount}\n")
2. 获取所有投资产品的名称,以及对应的所有用户投资记录
# 用prefetch_related预加载关联的钱包记录,适合反向多关联查询 investments = InvestmentName.objects.prefetch_related('wallet_set').all() for inv in investments: print(f"投资产品: {inv.name}") print("相关投资记录:") for wallet in inv.wallet_set.all(): print(f"- 投资者: {wallet.user.name}, 日期: {wallet.date}, 当前单价: {wallet.current_price}") print("---")
3. 统计某个用户的总投资金额
from django.db.models import Sum user = User.objects.get(id=1) total_investment = Wallet.objects.filter(user=user).aggregate(total=Sum('amount'))['total'] print(f"用户{user.name}的累计投资金额: {total_investment}")
4. 查询某一天的所有钱包记录
from datetime import date target_date = date(2024, 5, 20) # 同时预加载用户和投资名称,一次性获取所有关联数据 daily_records = Wallet.objects.filter(date=target_date).select_related('user', 'investment') for record in daily_records: print(f"用户: {record.user.name}, 投资产品: {record.investment.name}, 金额: {record.amount}")
实用小技巧
- 用
select_related处理正向外键/一对一关联,prefetch_related处理反向关联/多对多,能大幅提升查询效率,避免N+1查询问题。 - 如果不确定查询对应的SQL语句,可以在查询后加
.query查看,比如print(Wallet.objects.filter(user=user).select_related('investment').query),方便排查问题。
内容的提问来源于stack exchange,提问作者Maruti Nerli
相关产品推荐
相关产品推荐

