SQLAlchemy查询通过外键连接的表

4

我正在尝试通过Flask-SQLAlchemy查询显示来自MySQL的数据,并将外键(category_id)更改为分配给category_id的名称。 更确切地说 - {{link1:“输入图像描述”src}}

使用查询,我想显示具有来自类别表的名称的项目,而不是category_id。

这是我的代码:

class MyEnum(enum.Enum):
    piece = "piece"
    kg = "kg"

class Category(db.Model):
    __tablename__ = 'category'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(25), nullable=False)

class Product(db.Model):
    __tablename__ = 'product'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(30), nullable=False)
    quantity = db.Column(db.Integer, nullable=False)
    product_type = db.Column(db.Enum(MyEnum), nullable=False)
    category_id = db.Column(db.Integer, db.ForeignKey('category.id'))
    description = db.Column(db.String(255))

    category = db.relationship("Categ{{user.id}}ory",
                            backref=('products'))


    def __init__(self,name, quantity, product_type, category_id, description):
        self.name = name
        self.quantity = quantity
        self.product_type = product_type
        self.category_id = category_id
        self.description = description


db.create_all()
db.session.commit()

@app.route('/grocery-list', methods=['GET'])
def display_data():
    data = Product.query.all()
    category_name = db.session.query(Product).join(Category, Product.category_id == Category.name)
    return render_template('query_database.html', data=data, category_name = category_name)

#query_database.html
<body>
    {% for user in data %}
        <li>{{user.id}}.   {{user.name}}  {{user.quantity}}  {{user.product_type}} Category {{user.category_id}}  {{user.description}}</li>
    {% endfor %}
    {{ category_name }}
</body>

query_Database.html的结果:

3. Ziemniaczki 2 MyEnum.kg Category 1 Na obiad

SELECT product.id AS product_id, product.name AS 
product_name,product.quantity AS product_quantity, product.product_type AS product_product_type, product.category_id AS product_category_id, 
product.description AS product_description FROM product INNER JOIN category ON product.category_id = category.name 

问题:

1)如何创建这样的查询?我已经了解了在纯SQL中应该如何编写,但在SqlAlchemy文档中找不到相应的等效方法:

select p.name, c.name
from product as p
join category as c
on c.id = p.category_id 

2) MyEnum.kg在那里做什么?如何从此视图中删除My.Enum?

编辑 - 成功

如果有人需要,就把工作代码留下来。

@app.route('/grocery-list', methods=['GET'])
def display_data():
    data = db.session.query(Product, Category).join(Category).all()
    return render_template('query_database.html', data=data)

    {% for user, category in data  %}
    <li>{{user.id}}. {{user.name}}  {{user.quantity}}  {{user.product_type}} Category {{user.category.name}}  {{user.description}}</li>
    {% endfor %}

解决方案

在连接表之后,在模板文件中需要使用

{{ category.name }}

来解包类别名称的值。

{{user.category.name}}  

你能解释一下你想通过 Product.category_id == Category.name(将整数列与文本列进行比较)实现什么吗? - Ilja Everilä
那个部分只是我的测试(正如你所看到的那样失败了)。通过文档,我尝试找到替换 Product.category_idCategory.name 的解决方案。我不是为了显示数字而编写代码,而是将 category 表中的 Category.name 分配给这个数字。 - michael93pl
1个回答

7

1) 如何创建这样的查询?我了解了纯SQL中应该如何编写,但在SqlAlchemy的文档中找不到等价物

以下链接可能对您有用:

由于您已经定义了 ProductCategory 之间的ORM关系,因此您可以通过预加载相关类别和产品来进行查询操作:

data = Product.query.options(db.joinedload(Product.category)).all()

然后您可以在模板中访问user.category.name而不会产生新的查询。另一个更像SQL的解决方案是获取Product,Category元组,这似乎是您需要的:

# No need to explicitly define the ON clause of the join, unless you
# really want to. SQLAlchemy examines the foreign key(s) and does what
# needs to be done.
data = db.session.query(Product, Category).join(Category).all()

然后在你的模板中,你需要解包结果元组:

<!-- I don't understand why it's called "user" -->
{% for user, category in data %}
    ...
{% endfor %}

2) MyEnum.kg到底是什么?如何从该视图中删除My.Enum?

那只是一个枚举的字符串表示:

In [4]: str(MyEnum.kg)
Out[4]: 'MyEnum.kg'

如果您对{{user.product_type}}不满意,您需要修改它以适应您的需要。您已经使用了SQLAlchemy的Enum类型和遵循PEP-435规范的枚举类作为该列:

当使用枚举类时,枚举对象在输入和输出时都被使用,而不是像纯字符串枚举类型一样使用字符串...


首先,非常感谢您的回复!我会立即仔细阅读您提到的链接以扩展我的知识。如果我理解正确,使用def display_date()我们只返回一个参数data = db.session.query(Product, Category).join(Category).all(),视图应该看起来像{% for user, category in data %}?为什么我们要在其中迭代类别?在当前“设置”下,输出保持不变。 - michael93pl
如果你想使用更明确和类似SQL的风格,那么是的。你需要“按类别迭代”,因为查询结果是一个product, related_category元组列表。这就是你使用query(Product, Category)所要求的。 - Ilja Everilä
所以当前的更改对输出没有影响。我在问题中进行了编辑,以显示所需的输出。 - michael93pl
可能正是我的问题所在,我没有改变。我已经尝试找到模板的解决方案,但似乎没有什么作用(尽管这可能很容易修复)。 - michael93pl
{{category.name}},假设您已经使用该变量名进行了解压缩。 - Ilja Everilä
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接