Вопрос

How do I search a list in many to many relationship, in sqlalchemy. In the example below I want to search for posts containing a set of tags. I can search for the posts containing a particular tag, but not a list of tags:

class Post(Base):
    __tablename__ = 'posts'
    id    = Column(Integer, primary_key=True)
    text  = Column(Text)
    tags  = relationship('Tag', secondary=tagmap, backref='posts')
    def __init__(self, id, text, tags):
        self.id = id
        self.text = text
        self.tags = tags

class Tag(Base):
    __tablename__ = 'tags'
    id    = Column(Integer, primary_key=True)
    name  = Column(String)
    def __init__(self, id, name):
        self.id = id
        self.name = name

def postsTest():
    tag1 = Tag(1, "aa")
    tag2 = Tag(2, "bb")
    tag3 = Tag(3, "cc")
    sess.add(tag1)
    sess.add(tag2)
    sess.flush()

    post = Post(1, "blah:", [tag1, tag2, tag3])
    sess.add(post)
    sess.flush()

    # this works
    for p in sess.query(Post).filter(Post.tags.contains(tag1)).all():
        print str([tag.name for tag in p.tags])

    #this doesn't
    for p in sess.query(Post).filter(Post.tags.contains([tag2, tag3])).all():
        print str([tag.name for tag in p.tags])

postsTest()
Это было полезно?

Решение

Below should do the trick:

q = sess.query(Post).filter(
        and_(
            Post.tags.contains(tag2),
            Post.tags.contains(tag3),
            )
        ).all()

You can replace and_ with or_ if you wish as well add as many as you want.

However, I do not think that you want to search for Posts of specific tag, I think you want to find post which have specific tag name(s). If this is the case, you should do:

# get all Posts with has a least one tag from the list ["aa", "bb"]
q = sess.query(Post).filter(Post.tags.any(Tag.name.in_(["aa", "bb"])))

# get all Post with all of the tags in the list ["aa", "bb"]
q = sess.query(Post).filter(
        and_(
            Post.tags.any(Tag.name.in_(["aa"])),
            Post.tags.any(Tag.name.in_(["bb"])),
            )
        )
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top