如何用Django查询生成以父模型名称为键的子模型值字典?
如何生成以Kid名称为键、玩具元组列表为值的Django字典
嘿,我来帮你搞定这个需求!基于你给出的一对多模型,我们可以高效生成目标字典,还能避免常见的N+1查询问题,具体实现如下:
先补全规范的模型代码(Django 2.0+需要on_delete参数)
class Kid(models.Model): name = models.CharField(max_length=200) class Toy(models.Model): name = models.CharField(max_length=200) material = models.CharField(max_length=200) owner = models.ForeignKey(Kid, on_delete=models.CASCADE) # 补充on_delete参数,符合Django规范
高效生成目标字典的代码
我们用prefetch_related预加载关联数据,避免多次查询数据库,然后通过字典推导式快速构建结果:
# 预加载所有孩子及其对应的玩具,一次性查询数据库 kids_with_toys = Kid.objects.prefetch_related('toy_set').all() # 生成目标字典 kid_toys_dict = { kid.name: [(toy.name, toy.material) for toy in kid.toy_set.all()] for kid in kids_with_toys }
代码说明
prefetch_related('toy_set'):Django会一次性加载所有Kid关联的Toy对象,相比逐个Kid查询玩具,能大幅减少数据库请求次数,数据量越大优势越明显。- 字典推导式:遍历每个Kid,以孩子的
name作为键,用列表推导式把该孩子的所有玩具转换成(玩具名, 材质)的元组列表作为值。
可选优化:设置related_name
如果给Toy的ForeignKey设置related_name,代码会更易读:
# 修改Toy模型的ForeignKey字段 owner = models.ForeignKey(Kid, on_delete=models.CASCADE, related_name='toys') # 此时生成字典的代码可以改成 kid_toys_dict = { kid.name: [(toy.name, toy.material) for toy in kid.toys.all()] for kid in kids_with_toys }
示例结果
假设数据库里有这些数据:
- 孩子"小明"有玩具("积木", "塑料")、("玩偶", "毛绒")
- 孩子"小红"有玩具("遥控车", "金属")
生成的字典会是这样:
{ "小明": [("积木", "塑料"), ("玩偶", "毛绒")], "小红": [("遥控车", "金属")] }
内容的提问来源于stack exchange,提问作者bwrabbit
相关产品推荐
相关产品推荐

