在Django中关联并遍历外键数据表
Django外键关联与数据遍历指南
嘿,我来帮你搞定这两个模型的关联和遍历问题~先咱们先把你的模型补全(毕竟现在的代码有点不完整),再一步步讲怎么关联查询和遍历数据。
第一步:完善你的模型
首先,你的PriceHistory模型里的外键缺少on_delete参数(Django 2.0+必填),而且Meta类没写完。假设你想给同一股票的同一交易日期设置唯一约束,补全后的模型应该是这样:
from django.db import models class Stock(models.Model): symbol = models.CharField( db_index=True, max_length=5, null=False, editable=False, unique=True ) def __str__(self): return self.symbol # 方便在后台和打印时看到股票代码 class PriceHistory(models.Model): stock = models.ForeignKey( Stock, related_name='StockHistory_stock', editable=False, on_delete=models.CASCADE # 当Stock被删除时,关联的PriceHistory也跟着删除 ) trading_date = models.DateField(db_index=True, null=False, editable=False) price = models.DecimalField(max_digits=12, decimal_places=5, null=False, editable=False) class Meta: # 确保同一股票同一日期只有一条价格记录 unique_together = ('stock', 'trading_date') ordering = ['-trading_date'] # 默认按交易日期倒序排列 def __str__(self): return f"{self.stock.symbol} - {self.trading_date}: {self.price}"
第二步:关联查询与遍历数据
接下来分两种场景来讲解:
1. 从PriceHistory到Stock(正向查询)
每个PriceHistory实例直接通过外键字段stock就能关联到对应的Stock对象,遍历起来很简单:
# 获取所有价格记录,遍历并打印对应的股票代码和价格 price_histories = PriceHistory.objects.all() for ph in price_histories: print(f"股票代码:{ph.stock.symbol},日期:{ph.trading_date},价格:{ph.price}") # 如果你只想获取某条价格记录对应的股票 single_ph = PriceHistory.objects.first() stock = single_ph.stock print(f"这条记录对应的股票是:{stock.symbol}")
2. 从Stock到PriceHistory(反向查询)
因为你设置了related_name='StockHistory_stock',所以每个Stock实例可以通过这个名称来获取所有关联的PriceHistory记录:
# 获取某一只股票(比如代码为'AAPL'的) stock = Stock.objects.get(symbol='AAPL') # 获取这只股票的所有历史价格记录 price_histories = stock.StockHistory_stock.all() # 遍历这些历史价格 for ph in price_histories: print(f"日期:{ph.trading_date},价格:{ph.price}") # 也可以过滤特定日期范围的记录 from datetime import date recent_histories = stock.StockHistory_stock.filter(trading_date__gte=date(2024,1,1))
💡 小提示:related_name的名字有点绕,建议改成更直观的,比如price_histories,这样代码可读性更高——把related_name='price_histories'改完后,就可以用stock.price_histories.all()来查询了。
第三步:优化查询性能(避免N+1问题)
如果要批量查询数据,直接遍历可能会触发多次数据库查询(比如遍历所有Stock再查各自的PriceHistory),这时候可以用prefetch_related或者select_related来优化:
# 一次性获取所有股票及其关联的历史价格,避免多次查询 stocks_with_histories = Stock.objects.prefetch_related('StockHistory_stock').all() for stock in stocks_with_histories: print(f"股票:{stock.symbol}") for ph in stock.StockHistory_stock.all(): print(f" {ph.trading_date}: {ph.price}") # 如果是从PriceHistory查Stock,用select_related优化 price_histories = PriceHistory.objects.select_related('stock').all() for ph in price_histories: print(f"{ph.stock.symbol} - {ph.trading_date}: {ph.price}")
内容的提问来源于stack exchange,提问作者Saqib Ali
相关产品推荐
相关产品推荐

