如何遍历一对多关系的查询结果?

0 投票
1 回答
568 浏览
提问于 2025-04-16 10:48

我对如何过滤和显示一对多关系有点困惑。

根据这个问题这篇文章还有我之前的问题),我在Item之外创建了一个新的引用属性Tag

class Item(db.Model):
    ...
    title = db.StringProperty()
    url = db.StringProperty()
    image_source_url = db.StringProperty()
    ....

class Tag(db.Model):
    item = db.ReferenceProperty(Item, collection_name = "image_tags")
    tag = db.StringProperty()

我在Tag中添加了两个新项,现在表格看起来是这样的:

Key: ahNzYz...
ID: 269
Key Name:
item: ahNzYXJh...
      Item: id=268
tag: glam

Key: ahNxyz...
ID: 270
Key Name:
item: ahNzYXJh...
      Item: id=264
tag: casual

在我的SortFormHandler中,我进行了这个查询,并尝试遍历结果:

class SortFormHandler(webapp.RequestHandler):
    def get(self):        
        query = Tag.all()
        query.filter("tag", "glam")

        for item in query.image_tags:
            self.response.out.write("""<a href="%s"><image src="%s" height="110">%s</a>""" % 
                                       (item.url, item.image_source_url, item.title)  )

这导致了属性错误:

AttributeError: 'Query' object has no attribute 'image_tags'

我尝试了其他组合,但都没有成功。如果有人能解释一下这个是怎么回事,我就能理解如何遍历结果了。

谢谢。

更新

我尝试了Daniel Roseman的回答,像这样:

        for tag in query:
            self.response.out.write("tag is: %s" % tag.tag)
            for item in tag.image_tags:
                self.response.out.write("""<a href="%s"><image src="%s" height="110">%s</a>""" % 
                                       (item.url, item.image_source_url, item.title)  )

但这给出了

AttributeError: 'Tag' object has no attribute 'image_tags'

有什么建议可以解决这个问题吗?

更新 2

我看到在Tag表中,引用项的ID存储在item这一列下。我该如何获取这个ID?我尝试了

tag.item

在这一行

        for tag in query:
            self.response.out.write("tag is: %s. ID is: %s" % (tag.tag, tag.item))

但这只返回了对象:

tag is: glam. ID is: <__main__.Item object at 0x06875EB0>

更新 3

好的,我找到了获取引用项的键名的方法:

        for tag in query:
            self.response.out.write(ID is: %s" % (tag.item.key()))

所以

tag.item.key()

返回了我需要使用的项的键。我该如何获取该项的urltitle等信息?我该如何显示它?

更新 4

这似乎有效(至少对一个标签来说):

for tag in query:
    referenced_item_key = tag.item.key()
    item = Item.get(referenced_item_key)
    self.response.out.write("""<a href="%s"><image src="%s" height="110">%s</a>""" % 
                                       (item.url, item.image_source_url, item.title)  )

注意:名称有点混淆,这里的item指的是Tag中的引用列:

    referenced_item_key = tag.item.key()

我应该把这个项命名为其他名字:

    item = Item.get(referenced_item_key)

相关问题:

1 个回答

1

这里你需要用到两个循环。query 是一个包含标签对象的列表。每个标签对象里面又有一个物品的列表。所以你需要先遍历 query,然后再遍历每个标签里的物品。

不过,还有第二个问题:ReferenceProperty 的方向是错的。根据我的理解,ReferenceProperty 就像普通 Django 中的 ForeignKey:也就是说,它是一种一对多的关系,其中定义这个属性的模型是“一”的那一方。但你似乎想要每个标签对应多个物品,然后再去遍历这些物品:所以你需要把 ReferenceProperty 放在物品模型上。

这样,你就可以进行两个循环了:

 for tag in query:
     self.response.out.write('header for tag %s' % tag.tag)
     for item in tag.image_tags:
         self.response.out.write('detail for each item')

撰写回答