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

添加related_name后,如何编写Django ORM一对一反向关联查询?

问题描述

我定义了以下两个Django模型,已在Service模型的一对一字段中添加了related_name="service_client":

class Client(models.Model):
    first_name
    last_name
    car # Client's car to be serviced


class Service(models.Model):
   service_name 
   service_type
   service_date
   client = models.OneToOneField(Client, on_delete=models.CASCADE, verbose_name="Client served", related_name="service_client")
   
   def __str__():
       return f"Client {self.client} was serviced at {self.service.date}"

我需要以表格形式展示所有客户数据(示例表格如下),需求是获取每个客户是否已接受服务、服务日期的信息,请问如何在views.py中实现?是否需要在Client模型中新增布尔字段?还是通过更合理的ORM关联查询实现?若为Django常见问题,请提供官方文档指引,同时给出具体查询示例。

示例表格:

名姓车辆(品牌/型号)是否已服务?服务日期
JohnWatsonToyota Auris是2023-02-01
BobKilickiToyota Corolla是2023-02-01
MarkSmithHonda Civic否--------
DavidBobsonVW Polo是2023-02-03
AndrewHutchinsonRenault Clio否--------

解决方案

不需要新增布尔字段,ORM关联查询是更优方案

一对一关系本身可通过判断关联对象是否存在来确定客户是否接受过服务,新增字段会造成数据冗余,还需额外维护字段一致性,完全没必要。

具体实现步骤

1. 在views.py中构建查询集

通过Django ORM的annotate结合Case/When条件表达式,直接给每个Client对象添加两个自定义注解字段,用于模板渲染:

from django.db.models import Case, When, BooleanField, Value, CharField
from .models import Client

def client_list(request):
    # 关联查询并添加注解字段
    clients = Client.objects.annotate(
        has_service=Case(
            When(service_client__isnull=False, then=Value(True)),
            default=Value(False),
            output_field=BooleanField()
        ),
        service_date_display=Case(
            When(service_client__isnull=False, then='service_client__service_date'),
            default=Value('--------'),
            output_field=CharField()
        )
    ).all()
    
    # 将查询集传递给模板
    return render(request, 'client_list.html', {'clients': clients})

2. 模板中渲染表格

在client_list.html模板中,直接使用注解后的字段生成目标表格:

<table>
    <thead>
        <tr>
            <th>名</th>
            <th>姓</th>
            <th>车辆(品牌/型号)</th>
            <th>是否已服务?</th>
            <th>服务日期</th>
        </tr>
    </thead>
    <tbody>
        {% for client in clients %}
        <tr>
            <td>{{ client.first_name }}</td>
            <td>{{ client.last_name }}</td>
            <td>{{ client.car }}</td>
            <td>{% if client.has_service %}是{% else %}否{% endif %}</td>
            <td>{{ client.service_date_display }}</td>
        </tr>
        {% endfor %}
    </tbody>
</table>

Django官方文档相关指引

  • 关于annotate注解查询:可参考官方文档的「Annotations」章节,学习如何为查询集添加自定义字段。
  • 关于Case/When条件表达式:参考官方文档的「Conditional Expressions」章节,了解ORM中的条件判断实现逻辑。

内容的提问来源于stack exchange,提问作者PrertoQuebas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 03:31:37