Django关联查询:筛选指定Listing与Bidder对应的Bid及Listing记录
需求与解决方案
模型定义
class User(AbstractUser): pass class Listing(models.Model): name = models.CharField('Listing Name', max_length=64) description = models.TextField() owner = models.ForeignKey(User, related_name="listings", on_delete=models.CASCADE) active = models.BooleanField('Active', default=True) class Bid(models.Model): listing = models.ForeignKey(Listing, related_name="listing_bids", on_delete=models.CASCADE) bidder = models.ForeignKey(User, related_name="user_bids", on_delete=models.CASCADE) amount = models.DecimalField(max_digits=7, decimal_places=2) class Meta: unique_together = ('listing', 'bidder',)
逻辑上,一个Listing可接收不同User的多个Bid,且通过unique_together约束,同一用户对同一Listing只能存在一条Bid记录。
需求
获取指定Listing(x)与指定User(y)对应的Listing行及关联的Bid行,要求仅返回一条Bid记录(若存在)或None,不通过手动循环实现。
解决方案
方法1:从Listing对象关联筛选
先获取目标Listing,再通过关联的listing_bids筛选指定用户的Bid:
# 假设已知listing的pk为x,user的pk为y listing = Listing.objects.get(pk=x) # 通过user实例筛选 bid = listing.listing_bids.filter(bidder__pk=y).first() # 或者通过username筛选 bid = listing.listing_bids.filter(bidder__username="指定用户名").first()
first()方法会返回匹配的第一条记录(因唯一约束最多一条),无匹配则返回None。
方法2:直接从Bid模型查询(更高效)
直接查询Bid表,同时通过select_related一次性加载关联的Listing数据,避免二次数据库查询:
# 通过user实例和listing实例查询 bid = Bid.objects.filter(listing__pk=x, bidder__pk=y).select_related('listing').first() # 或者通过username和listing pk查询 bid = Bid.objects.filter(listing__pk=x, bidder__username="指定用户名").select_related('listing').first()
若需单独获取Listing对象,可通过bid.listing直接访问。
方法3:使用get()方法(需处理异常)
如果需要明确判断记录是否存在,可使用get(),但需捕获不存在的异常:
from django.core.exceptions import ObjectDoesNotExist try: bid = Bid.objects.get(listing__pk=x, bidder__pk=y) except ObjectDoesNotExist: bid = None
这种方式适合必须确保记录存在的场景,否则用first()更简洁。
内容的提问来源于stack exchange,提问作者Wavesailor
相关产品推荐
相关产品推荐

