如何在Django中通过关联关系输出对象?现有模板写法是否可行?
Django模板中关联对象遍历写法问题
我不太清楚如何用数据库术语准确描述该需求,我希望输出与另一个对象存在关联关系的对象,例如通过order__orderitem.product.title这样的形式获取商品标题。
以下是我的代码:
models.py
class Order(models.Model): status_types = [ ("Ordered", "Ordered"), ("Sent", "Sent"), ("Delivered", "Delivered"), ("Extended", "Extended"), ("Returned", "Returned"), ] user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) order_date = models.DateTimeField() return_date = models.DateTimeField(null=True) status = models.CharField(choices=status_types, default="Ordered", max_length=100) total = models.IntegerField(null=False) payment = models.OneToOneField(Payment, on_delete=models.CASCADE, null=False, blank=False) shipping = models.ForeignKey(Shipping, on_delete=models.CASCADE, null=False, blank=False) first_name = models.CharField(max_length=255, null=False, blank=False) last_name = models.CharField(max_length=255, null=False, blank=False) phone = models.CharField(max_length=12, null=False, blank=False) city = models.CharField(max_length=255, null=False, blank=False, default=None) zip_code = models.CharField(max_length=10, null=False, blank=False, default=None) street = models.CharField(max_length=255, null=False, blank=False, default=None) building_number = models.CharField(max_length=10, null=False, blank=False, default=None) apartment_number = models.CharField(max_length=10, null=True, blank=True, default=None) class OrderItem(models.Model): product = models.ForeignKey(Product, on_delete=models.CASCADE) order = models.ForeignKey(Order, on_delete=models.CASCADE) user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True) price = models.IntegerField(null=False, blank=False, default=15) debt = models.IntegerField(null=True, default=0)
orders.html
{% for item in object_list %} {% for it in item__OrderItem %} {{ it.product.title }} {% endfor %} {% endfor %}
请问这种写法是否可行?
回答
你模板里的item__OrderItem写法完全不可行,Django模板中访问关联对象要遵循以下规则:
- 默认反向关联管理器:因为
OrderItem通过外键order关联到Order,Django会自动为Order模型生成一个反向关联查询管理器,默认名称是orderitem_set(小写模型名 +_set)。所以正确的遍历写法应该是:
{% for item in object_list %} {% for it in item.orderitem_set.all %} {{ it.product.title }} {% endfor %} {% endfor %}
- 自定义关联名称(更推荐):如果觉得默认的
orderitem_set不够直观,可以在OrderItem的外键字段里设置related_name参数,修改模型代码:
class OrderItem(models.Model): # ... 其他字段 order = models.ForeignKey(Order, on_delete=models.CASCADE, related_name='order_items') # ... 其他字段
之后模板里就可以用更清晰的名称遍历:
{% for item in object_list %} {% for it in item.order_items.all %} {{ it.product.title }} {% endfor %} {% endfor %}
- 性能优化建议:如果订单数量较多,建议在视图中使用
prefetch_related预取关联的OrderItem数据,避免N+1查询问题,比如在视图里写:
orders = Order.objects.all().prefetch_related('order_items') # 对应自定义的related_name # 或者用默认名称 orders = Order.objects.all().prefetch_related('orderitem_set')
内容的提问来源于stack exchange,提问作者Tylzan
相关产品推荐
相关产品推荐

