python - 在反向关系列表中过滤 Django 模型
问题描述
我有两个 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="鲍勃"。
建议?
解决方案
我稍微修改了@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 传递给此函数,而不仅仅是名称,这将使过滤更容易(你不需要一个集合并直接按 id 过滤)和更高效(通过使用数据库索引......或者你会有索引 person_name 以及)
推荐阅读
- python - 如何在列表中找到匹配条件的第一个元素?
- rabbitmq - 为什么 RabbitMQ 客户端在将实际消息体发送到 RabbitMQ 代理之前发送一个方法帧和一个内容帧?
- .net-core - UTF8.Encoding.UTF8.GetBytes 在 Windows 和 Linux 上返回不同的结果
- jupyter-notebook - RISE JupyterNotebook 演示文稿的配置
- firebase - 在所有节点上强制执行身份验证,而不在 firebase 实时数据库中的每个叶子上应用规则
- flutter - Flutter 网页文件 i/o
- python - python - 如何在python的beautifulsoup中解析多个标签及其类?
- python - 在 Keras 回调中更新样本权重?
- html - 如何将宽度小于 100% 的图像居中?
- visual-studio-code - 启动时在 VSCode 开发工具中运行 JavaScript