如何在自引用表中返回孩子的父母?

时间:2014-12-21 20:40:00

标签: flask sqlalchemy flask-sqlalchemy

我构建了这个模型来管理我网站的内容。它似乎工作得很好,除了我无法弄清楚如何表明"父母"一个给定的孩子"。

数据结构

这使我可以将内容组织到树中。

Parent
--- child 1
--- child 2
--- child 3
--------grandchild 1
--------grandchild 2

MODEL

class Service(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    parent_id = db.Column(db.Integer, db.ForeignKey('service.id'))
    parent = db.relationship('Service', remote_side=[id], backref='children')
    slug = db.Column(db.String(120), unique=True)
    label = db.Column(db.String(80), unique=True)
    body = db.Column(db.UnicodeText)
    meta_desc = db.Column(db.UnicodeText)
    meta_kw = db.Column(db.UnicodeText)
    date_create = db.Column(db.DateTime)

    def __unicode__(self):
        return self.slug

    def __repr__(self):
        return self.label

这有效.....

>>> Service.query.filter_by(slug="/about").all()
[About]

这样......

>>> Service.query.filter_by(parent=None).all()
[]

这不起作用

>>> Service.query.filter_by(parent="/about").all()

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/jwogrady/.virtualenvs/medcol/lib/python2.7/site-packages/sqlalchemy/orm/query.py", line 1296, in filter_by
    for key, value in kwargs.items()]
  File "/Users/jwogrady/.virtualenvs/medcol/lib/python2.7/site-packages/sqlalchemy/sql/operators.py", line 298, in __eq__
    return self.operate(eq, other)
  File "/Users/jwogrady/.virtualenvs/medcol/lib/python2.7/site-packages/sqlalchemy/orm/attributes.py", line 176, in operate
    return op(self.comparator, *other, **kwargs)
  File "/Users/jwogrady/.virtualenvs/medcol/lib/python2.7/site-packages/sqlalchemy/orm/relationships.py", line 1002, in __eq__
    other, adapt_source=self.adapter))
  File "/Users/jwogrady/.virtualenvs/medcol/lib/python2.7/site-packages/sqlalchemy/orm/relationships.py", line 1338, in _optimized_compare
    value = attributes.instance_state(value)
AttributeError: 'str' object has no attribute '_sa_instance_state'

对于给定的孩子,我该如何获得父母?

1 个答案:

答案 0 :(得分:1)

要获取所有具有slug“about”的父级的服务,请使用has比较:

Service.query.filter(Service.parent.has(Service.slug == '/about')).all()

或者,为了在非常大的表上获得更好的性能,请使用别名和连接:

parent = db.aliased(Service)
Service.query.join((parent, parent.id == Service.parent_id)).filter(parent.slug == '/about').all()

如果您的字面意思是“如何获取给定服务的父服务”,则只需使用s.parent从实例访问它。

相关问题