中間テーブルとは #2
概要
本記事では、中間テーブルのデータ表示方法を解説する。「中間テーブルとは #1」に続く記事なので、より詳細を知りたい方はそちらを参考いただきたい。
中間テーブルのおさらい
中間テーブルのコードを以下に記載する。
order_items = db.Table('order_items',
db.Column('order_id', db.Integer, db.ForeignKey('order.id'), primary_key=True),
db.Column('product_id', db.Integer, db.ForeignKey('product.id'), primary_key=True)
)
class Order(db.Model):
id = db.Column(db.Integer, primary_key=True)
status = db.Column(db.String(), nullable=False)
products = db.relationship('Product', secondary=order_items,
backref=db.backref('orders', lazy=True))
class Product(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(), nullable=False)
order_items / Order / Productの三つのテーブルが存在し、order_itemsが中間テーブルである。
- Orderテーブル
- 顧客の注文を管理するテーブル。注文idと注文状態(準備中、提供ずみ等)がカラムにある。
- Productテーブル
- 商品情報を管理するテーブル。商品idと商品名がカラムにある。
- order_itemsテーブル
- order_idとproduct_idがカラムにある。それぞれ、Orderテーブルのid、そしてProductテーブルのidと紐づくように管理されている。
Order -> Product, Product -> Orderの参照
Order -> Productの参照
各注文について、「どんな商品があったっけ?」とか、もしくは各商品に対して、「どの注文に含まれてたっけ?」と参照したい場合がある。そういうときに、Orderテーブルの以下コードが重要となる。
products = db.relationship('Product', secondary=order_items,
backref=db.backref('orders', lazy=True))
Orderテーブルの中でProductテーブルの定義がされているため、そちらへの情報参照が可能となる。
@app.route('/order/<int:order_id>/products', methods=['GET'])
def get_products_by_order(order_id):
order = Order.query.get(order_id)
if not order:
return jsonify({'error': 'Order not found'}), 404
products = [{'id': product.id, 'name': product.name} for product in order.products]
return jsonify(products)
例えば、上記のように情報参照できる。まず最初に、order = Order.query.get(order_id)によって、特定のorder情報を取得できる。そのorder情報を取得後、order.productsによって、その商品情報を取得できる。なぜなら、先ほども説明したように、すでにOrderテーブルで、productsの定義がされているからである。
つまり下記コードは、特定のorderのidに対し商品情報を取得して、それをリスト化した情報をproductsに格納するコードである。
products = [{'id': product.id, 'name': product.name} for product in order.products]
Product -> Orderの参照
逆にProductテーブルからOrderテーブルの参照をしたい場合、backrefでordersが定義されているので、それを利用する。
products = db.relationship('Product', secondary=order_items,
backref=db.backref('orders', lazy=True))
例えば、コードは以下のイメージ。
- まず、product = Product.query.get(product_id)で、特定のproductのid情報を取得する。例えば、product id = 3のproduct情報を取得する。
- 次に、そのproduct id = 3のorders情報を取得する。id = 3であるorders情報を全て取得しリスト化して、ordersに格納する。
@app.route('/product/<int:product_id>/orders', methods=['GET'])
def get_orders_by_product(product_id):
product = Product.query.get(product_id)
if not product:
return jsonify({'error': 'Product not found'}), 404
orders = [{'id': order.id, 'status': order.status} for order in product.orders]
return jsonify(orders)
Frontendでの情報表示
上記内容により、Backend側のエンドポイントは開発できた。次に、Frontendでのデータ表示を説明する。全体のコードは、以下の通り。
<template>
<div>
<h2>Products for Order ID: {{ orderId }}</h2>
<ul>
<li v-for="product in products" :key="product.id">
{{ product.name }}
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
orderId: null,
products: []
};
},
created() {
this.orderId = this.$route.params.orderId; // Assuming you're using vue-router
this.fetchProducts();
},
methods: {
async fetchProducts() {
try {
let response = await fetch(`/order/${this.orderId}/products`);
if (response.ok) {
this.products = await response.json();
} else {
console.error("Error fetching products:", response.statusText);
}
} catch (error) {
console.error("There was an error fetching the products:", error);
}
}
}
};
</script>
まず最初に、methodsにてfetchProducts関数を作る。ここでは、先ほど作ったエンドポイントからlet response = await fetch(/order/${this.orderId}/products
);という形でresponseに情報格納して、それをthis.products = await response.json();とjson化しproductsに格納する。
async fetchProducts() {
try {
let response = await fetch(`/order/${this.orderId}/products`);
if (response.ok) {
this.products = await response.json();
} else {
console.error("Error fetching products:", response.statusText);
}
} catch (error) {
console.error("There was an error fetching the products:", error);
}
そして下記コードにて、for-loopでproductsリストの各情報を表示する。
<li v-for="product in products" :key="product.id">
{{ product.name }}
</li>
まとめ
中間テーブルの情報表示って、どうやってやるんだっけ?と気になって、備忘録的に記事を作成した。疑問点、不明点、質問があれば、コメントお願いします。
Discussion