获取交叉引用模型

2024-04-25 08:15:36 发布

您现在位置:Python中文网/ 问答频道 /正文

我在访问代码中的交叉引用(through)模型时遇到问题。你知道吗

从下面的代码可以看出,我的交叉引用模型中有一个字段,我想通过声音文件模型来选择它,但我似乎不知道如何选择。你知道吗

我对python和peewee还不熟悉,所以请容忍我。我有编程经验,但不是python。如果你能提供任何帮助,我将不胜感激。你知道吗

一小块土地: 我有一个存储库,在内存中保存一个声音文件记录列表。我正在遍历这些记录,并尝试访问交叉引用模型(该模型中的字段)。每个模型扩展的BaseModel只是建立了Meta类。你知道吗

声音文件模型

from peewee import *
from OgmaChatBot.entities.BaseModel import BaseModel


class SoundFile(BaseModel):
    file_name = TextField()
    short_name = TextField()
    command_available = IntegerField(constraints=[SQL("DEFAULT 0")])

    @staticmethod
    def get_all():
        return SoundFile.select()

    @staticmethod
    def get_one(key):
        return SoundFile.get(SoundFile.id == key)

事件模型

from peewee import *
from OgmaChatBot.entities.BaseModel import BaseModel


class Event(BaseModel):
    event = TextField()

    @staticmethod
    def get_all():
        return Event.select()

    @staticmethod
    def get_one(key):
        return Event.get(Event.id == key)

SoundEvent模型(交叉引用模型)

from peewee import *
from OgmaChatBot.entities.BaseModel import BaseModel
from OgmaChatBot.entities.Event import Event
from OgmaChatBot.entities.SoundFile import SoundFile


class SoundEvent(BaseModel):
    sound_file = ForeignKeyField(
        column_name='sound_file_id',
        field='id',
        model=SoundFile,
        backref='sound_event'
    )
    event = ForeignKeyField(
        column_name='event_id', 
        field='id', 
        model=Event, 
        backref='sound_event'
    )
    username = TextField(null=True)

    @staticmethod
    def get_all():
        query = (SoundEvent
                 .select(SoundEvent, SoundFile, Event)
                 .join(SoundFile)
                 .switch(SoundEvent)
                 .join(Event))

        return query

    @staticmethod
    def get_one(key):
        query = (SoundEvent
                 .select()
                 .join(SoundFile)
                 .switch(SoundEvent)
                 .join(Event)
                 .where(SoundEvent.id == key))

        return query

Tags: keyfrom模型importeventidgetreturn
2条回答

根据OP的评论:

What I am trying to do is get access to the username field in the SoundEvent model, starting from the SoundFile model. In my repository, I have a list of SoundFile objects.

有两种方法。由于每个声音文件可能有0..n个SoundEvent对象,因此我们将执行以下操作:

for sound_file in sound_files:
    events = (SoundEvent
              .select(SoundEvent.username)
              .where(SoundEvent.sound_file == sound_file))
    print(sound_file.filename)
    for event in events:
        print(' * ', event.username)

既然你已经宣布SoundEvent.sound\u文件使用backref="sound_event"外键,您也可以这样做,这是等效的(尽管考虑将backref sound\u事件设为复数):

for sound_file in sound_files:
    print(sound_file.filename)
    for event in sound_file.sound_event:
        print(' * ', event.username)

最后一个选择是尝试使用prefetch()更有效地执行此操作,这在其实现中有点复杂,并且只能在分析之后使用:

sound_files_with_events = prefetch(sound_files, SoundEvent)
for sound_file in sound_files_with_events:
    print(sound_file.filename)
    for event in sound_file.sound_event:  # the backref is pre-populated!
        print(' * ', event.username)

你的问题不清楚你想做什么…但这里有一些基于你共享的staticmethod的例子:

@staticmethod
def get_all():
    query = (SoundEvent
             .select(SoundEvent, SoundFile, Event)
             .join(SoundFile)
             .switch(SoundEvent)
             .join(Event))

    return query

然后可以打印所有文件名:

for sound_event in SoundEvent.get_all():
    print(sound_event.sound_file.filename)

或打印所有事件:

for sound_event in SoundEvent.get_all():
    print(sound_event.event.event)

或者,也可以从SoundFile开始列出所有事件:

sound_file = SoundFile.get(SoundFile.filename == 'the-file.mp3')
events = (Event
          .select()
          .join(SoundEvent)
          .where(SoundEvent.sound_file == sound_file))
for event in events:
    print(event.event)

等效于两个连接:

events = (Event
          .select()
          .join(SoundEvent)
          .join(SoundFile)
          .where(SoundFile.filename == 'the-file.mp3'))
for event in events:
    print(event.event)

我希望这能澄清问题。你知道吗

相关问题 更多 >