python - Django:聚合多对多值的查询集
问题描述
我有 MyUser 模型,其中包含 ForeignKey 和 ManyToMany 相关领域的城市和技能:
帐户/模型.py
class MyUser(AbstractBaseUser):
email = models.EmailField()
city = models.ForeignKey('jobs.City')
skills = models.ManyToManyField('jobs.Skill')
工作/模型.py
class Skill(models.Model):
name = models.CharField()
class City(models.Model):
name = models.CharField()
我需要创建一个以这种格式返回数据的查询集:
{'email': 'some@email.com', 'city': 'London', 'skills': ['Python', 'Java']},
{'email': 'another@email.com', 'city': 'Berlin', 'skills': ['JavaScript', 'C#', 'Python']},
...
MyUser.objects.values('email', 'city__name', 'skills__name')返回我需要的所有数据,但 ManytoMany 值分别返回,重复其他条目:
{'email': 'some@email.com', 'city': 'London', 'skills': 'Python'},
{'email': 'some@email.com', 'city': 'London', 'skills': 'Java'},
{'email': 'another@email.com', 'city': 'Berlin', 'skills': 'JavaScript'},
{'email': 'another@email.com', 'city': 'Berlin', 'skills': 'C#'},
{'email': 'another@email.com', 'city': 'Berlin', 'skills': 'Python'},
...
那么如何制作一个将 ManyToMany 值聚合为一组的查询集呢?
解决方案
https://docs.djangoproject.com/en/3.1/ref/models/querysets/#values
Django 文档对这种情况发出警告
警告:因为 ManyToManyField 属性和反向关系可以有多个相关行,包括这些行会对结果集的大小产生乘数影响。如果您在 values() 查询中包含多个此类字段,这将特别明显,在这种情况下,将返回所有可能的组合。
我已经搜索了替代方法,例如使用序列化程序,但我认为唯一的方法是遍历您的查询集并使用您想要的数据创建您自己的字典列表。
我建议为您的模型添加自定义属性
class MyUser(models.Model):
email = models.EmailField()
city = models.ForeignKey(City, on_delete=models.PROTECT)
skills = models.ManyToManyField(Skill)
@property
def get_skills(self):
skills = self.skills.all()
skills_list = []
for skill in skills:
skills_list.append(skill.name)
return skills_list
现在更容易获得技能属性的名称列表
users_list = []
for my_user in MyUser.objects.all():
users_list.append({
'email': my_user.email,
'city': my_user.city.name,
'skills': my_user.get_skills,
})
也许这不是您正在寻找的解决方案,也许这不是最好的方法,无论如何我希望这个答案会对您有所帮助。
推荐阅读
- javascript - 在javascript中使用正则表达式获取整数
- php - 如何上传已经上传的文件
- angularjs - 如何在 Ionic v1 中进行长按?
- javascript - 管理员可以使用 JavaSricpt SDK 将 Facebook 群组中的成员静音吗?
- laravel-5 - 尝试将 Laravel Homestead 连接到 sqlsrv 数据库时出现错误的网关错误
- oauth - 刷新的 OAuth2 令牌具有无效签名 (Azure AD OAuth2)
- javascript - Jquery Hide Show 似乎无法正常工作
- oracle - Oracle:按日期对结果进行排序,子组按相同日期
- php - 分别加入表插入和更新
- c# - 为什么在 CompensatingCollection 上调用 IQueryable 方法会引发 System.NotSupportedException