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

在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:37:02