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

Django多对一反向关联:单查询获取含日程的用户数据可行吗?

可以通过单次查询获取目标格式结果

方法一:使用Django REST Framework序列化器(适合API场景)

这是业务中最常用的实现方式,通过序列化器自动处理嵌套关联数据,配合prefetch_related避免N+1查询(实际是两次高效批量数据库查询,符合业务逻辑上的“一次查询”需求)。

首先定义序列化器:

from rest_framework import serializers
from .models import User, WorkSchedule

class WorkScheduleSerializer(serializers.ModelSerializer):
    class Meta:
        model = WorkSchedule
        fields = ["day_of_week", "start_time", "end_time"]

class UserSerializer(serializers.ModelSerializer):
    # 关联WorkSchedule集合,source对应反向关联的默认名称(模型名小写_set)
    work_schedule = WorkScheduleSerializer(many=True, source="workschedule_set")
    
    class Meta:
        model = User
        fields = ["id", "full_name", "work_schedule"]

然后执行查询并序列化:

# prefetch_related批量获取所有关联的排班数据
user = User.objects.prefetch_related("workschedule_set").get(id=1)
serializer = UserSerializer(user)
result = serializer.data  # 结果完全符合你要的格式

方法二:使用PostgreSQL聚合函数(真正单次数据库查询)

如果你的项目基于PostgreSQL数据库,可以利用数据库的JSON聚合能力,直接在一次查询中生成目标结构:

from django.contrib.postgres.aggregates import ArrayAgg
from django.db.models import Func, Value
from django.db.models.fields import JSONField
from .models import User

# 定义生成单个排班JSON对象的数据库函数
class ScheduleJSON(Func):
    function = "JSON_BUILD_OBJECT"
    output_field = JSONField()

# 单次查询聚合出结果
user_data = User.objects.annotate(
    work_schedule=ArrayAgg(
        ScheduleJSON(
            Value("day_of_week"), "workschedule__day_of_week",
            Value("start_time"), "workschedule__start_time",
            Value("end_time"), "workschedule__end_time"
        ),
        # 过滤掉无排班的空数据
        filter=models.Q(workschedule__isnull=False),
        distinct=False
    )
).values("id", "full_name", "work_schedule").get(id=1)

user_data就是直接符合要求的字典格式,全程仅触发一次数据库查询。

小提示:你的WorkSchedule模型中,ForeignKey字段名用user_id不符合Django规范,建议改成user,Django会自动在数据库生成user_id列,反向关联名称也会变成work_schedule_set,代码可读性更高。

内容的提问来源于stack exchange,提问作者Lê Hồng Nhật

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 12:43:11