我们再次尝试构建 a web-based tool帮助我们管理Software Carpentry讲习类。我们正在使用 Django ,尽管年代久远,它仍然是使用最广泛(并且记录最完备)的 Python 网络编程框架。不过,自从我在其中构建任何东西以来已经有几年了,而且我在一些事情上绊倒了。
例如,我的数据模型如下所示(删除了很多不相关的内容):
class Person(models.Model):
'''Someone we know.'''
email = models.CharField(max_length=STR_LONG, unique=True, null=True)
class Event(models.Model):
'''A workshop or other event.'''
slug = models.CharField(max_length=STR_LONG, unique=True)
class Role(models.Model):
'''The kinds of things people can do at workshops.'''
name = models.CharField(max_length=STR_MED)
class Task(models.Model):
'''Someone did something at some workshop.'''
event = models.ForeignKey(Event)
person = models.ForeignKey(Person)
role = models.ForeignKey(Role)
应用程序中的一个页面显示有关特定事件的信息。我想将所有在该事件中担任讲师的人的名字添加到页面中。如果我直接使用 SQL,我会这样写:
select Event.slug, group_contact(Person.email, ', ')
from Person join Event join Role join Task
on Person.id=Task.person and Event.id=Task.event and Role.id=Task.role
where Role.name='instructor'
group by Event.id;
我如何使用 Django 的 ORM 来做到这一点?根据this Stack Overflow question , 我可以使用 the 'regroup' tag in the view或 build a custom aggregator .前者因连接的多步骤性质而变得复杂,而后者感觉……复杂。我的直觉是,我应该能够将与特定 Event
中的讲师相对应的所有 Person
对象附加到该事件,然后在我的 View 中循环遍历它们。如果您知道如何执行此操作,我将不胜感激。
最佳答案
我认为您不需要这么复杂的查询。
对于任何特定事件,您可以这样做:
instructors = Task.objects.filter(event=my_event, role__name='instructor').select_related('person').values_list('person__email')
这将为您提供与该事件的任务相关且具有“讲师”角色的所有人员的电子邮件列表。不可否认,这是每个事件一个查询,而不是一个单一的大规模查询,但除非您计划在每页显示数百个事件,否则在清晰度方面进行权衡可能是值得的。
关于python - 相当于 Django ORM 中的 group_concat,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27358786/