2015-03-10 3 views
-1

Я использую SQLAlchemy не так долго. у меня есть эта структура:Как использовать подзапрос фильтра SQLAlchemy?

class Category(db.Model): 
    id = db.Column(db.Integer, primary_key=True) 
    name = db.Column(db.String(140)) 
    parent_id = db.Column(db.Integer, db.ForeignKey('category.id')) 
    parent = db.relationship("Category", remote_side=id, backref="sub_categories") 

    def __repr__(self): 
     return '<Category: {0.name}>'.format(self) 

class Object(db.Model): 
    id = db.Column(db.Integer, primary_key=True) 
    name = db.Column(db.String(140)) 
    category_id = db.Column(db.Integer, db.ForeignKey('category.id'), nullable=False) 
    category = db.relationship('Category', backref="objects") 
    values = db.relationship("Value", secondary="object_value", backref="objects") 

    def __repr__(self): 
     return '<Object: {0.name}>'.format(self) 


class Property(db.Model): 
    id = db.Column(db.Integer, primary_key=True) 
    name = db.Column(db.String(140)) 
    categories = db.relationship("Category", secondary="category_property", backref="properties") 

    def __repr__(self): 
     return '<Property: {0.name}>'.format(self) 


class Value(db.Model): 
    id = db.Column(db.Integer, primary_key=True) 
    value = db.Column(db.String(140)) 
    property_id = db.Column(db.Integer, db.ForeignKey("property.id")) 
    prop = db.relationship('Property', backref="values") 

    def __repr__(self): 
     return '<Value: {0.prop.name}={0.value}>'.format(self) 

db.Table(
    'category_property', db.Model.metadata, 
    db.Column('category_id', db.Integer, db.ForeignKey('category.id')), 
    db.Column('property_id', db.Integer, db.ForeignKey('property.id')) 
) 

db.Table(
    'object_value', db.Model.metadata, 
    db.Column('object_id', db.Integer, db.ForeignKey('object.id')), 
    db.Column('value_id', db.Integer, db.ForeignKey('value.id')) 
) 

использовано это я пытаюсь получить все объекты для категории, но в объектах, я хочу, чтобы получить только имущество, которое используется в категории. Я имею в виду примерно такие:

category = Category(name="Category") 

category_property = Property(name="Category Property") 
category.properties.append(category_property) 
value_category_property = Value(prop=category_property, value="value") 

other_property = Property(name="Other Property") 
value_other_property = Value(prop=other_property, value="value") 

obj = Object(name="Entry", category=category) 
obj.values.append(value_category_property) 
obj.values.append(value_other_property) 

db.session.add(obj) 
db.session.commit() 

for obj in db.session.query(Object)\ 
        .some_join_subquery()\ 
        .filter(Object.category == category.id)\ 
        .all(): 
    assert value_category_property in obj.values 
    assert value_other_property not in obj.values 

Что должно быть в some_join_subquery?

+0

Можете привести пример того, что вы действительно хотите получить от запроса? На данный момент вопрос не совсем ясен. Изменить: Возможно, если вы приведёте пример с исходным SQL-кодом, который вы ожидаете, мы можем помочь перевести его в SQLAlchemy. –

+0

Я хочу вернуть все «объекты» с предварительно загруженными соответствующими значениями. Но «значения» должны быть отфильтрованы «свойствами», которые включены в выбранную «категорию». Первое, что я пробовал - был построен необработанный SQL-запрос. Но это было слишком сложно для меня) На самом деле то, что я хочу, исключает «свойства» из предварительно загруженных «вещей», которые не включены в 'category'. @TomDalton – prokoptsev

ответ

0

Использовать свойство отношений any.

Object.query.filter(
    Object.category_id == category.id, 
    Object.values.any(name == 'Category Property'), 
    db.not_(Object.values.any(name == 'Other Property')) 
) 
Смежные вопросы