[英]Filter Django model on reverse relationship list
我有两个 Django 型号如下:
class Event(models.Model):
name = models.CharField()
class EventPerson(models.Model):
event = models.ForeignKey('Event',on_delete='CASCADE',related_name='event_persons')
person_name = models.CharField()
如果数据库中存在一个事件,它将恰好有两个与之相关的 EventPerson 对象。
我想要做的是确定是否存在具有给定名称的事件并且在该事件中具有给定的两个人(EventPersons)。 这可以在单个 Django 查询中完成吗?
我知道我可以编写这样的 python 代码来检查,但我希望有更有效的东西:
def event_exists(eventname,person1name,person2name):
foundit=False
for evt in Event.objects.filter(name=eventname):
evtperson_names = [obj.person_name in evt.event_persons.all()]
if len(evtperson_names) == 2 and person1name in evtperson_names and person2name in evtperson_names:
foundit=True
break
return foundit
或者最好重构模型,以便 Event 将 person1name 和 person2name 作为自己的字段,如下所示:
class Event(models.Model):
name = models.CharField()
person1name = models.CharField()
person2name = models.CharField()
这样做的问题是 person1 和 person2 没有自然顺序,即如果这些人是“Bob”和“Sally”,那么我们可以有 person1name="Bob" 和 person2name="Sally" 或者我们可以有 person1name="莎莉”和 person2name="鲍勃"。
建议?
您可以查询给定事件名称的EventPerson
对象,使用values_list
提取person_name
字段,并将返回的值列表转换为一个集合以进行无序比较:
def event_exists(eventname, person1name, person2name):
return set(EventPerson.objects.filter(event__name=eventname).values_list(
'person_name', flat=True)) == {person1name, person2name}
我稍微修改了@blhsing 答案,在名称上添加了一个过滤器。
def event_exists(eventname, person1name, person2name):
event_people = EventPerson.objects.select_related('event').filter(person_name__in=[person1name, person2name], event__name=eventname)
return set(event_people.values_list('person_name', flat=True)) person1name, person2name}
我建议将 EventPerson 对象或它们的 id 传递给这个 function 而不仅仅是名称,这将使过滤更容易(你不需要一个集合并直接按 id 过滤)和更高效(通过使用数据库索引......或者你会有索引 person_name 以及)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.