1

1人以上のインストラクターが教えることができる製品(クラス)を用意するシステムがあります。これらのインストラクターは製品を作成することもできます。その場合、開発者として製品を介してアクセスできる必要があります。ただし、その製品を利用できるすべてのインストラクターにもアクセスできるようにしたいと思います。

SQLAlchemyモデルを設定して、の1対多の関係だけでProduct.developerなく、の多対多の関係を設定する方法がわかりませんProduct.instructors

models.py

from app import db

instructors = db.Table('instructors',
    db.Column('instructor_id', db.Integer, db.ForeignKey('instructor.id')),
    db.Column('product_id', db.Integer, db.ForeignKey('product.id'))
)    


class Instructor(db.Model):
    id = db.Column(db.Integer, primary_key = True)
    name = db.Column(db.String(64))
    #courses qualified for etc

class Product(db.Model):
    id = db.Column(db.Integer, primary_key = True)
    courseName = db.Column(db.String(64))
    developer = db.relationship('Instructor', secondary=instructors,
        backref=db.backref('developed', lazy='dynamic'))
    instructors = db.relationship('Instructor', secondary=instructors,
        backref=db.backref('products', lazy='dynamic'))

    def __repr__(self):
        return '<Category> %r>' % (self.courseName)

views.py

from flask import render_template, flash, redirect
from app import app, models

@app.route('/product/<courseName>')
def show_product(courseName):
    product = models.Product.query.filter_by(courseName=courseName).first_or_404()
    return render_template('show-product.html', product=product)

テンプレート:show-product.html

<!-- extend base layout -->
{% extends "base.html" %}

{% block content %}
<br><b>Course Name:</b> {{product.courseName}}
<br><b>Curriculum developer:</b> 
    {% for developer in product.developer %}
        {{developer.name}}
    {% endfor %}
<br><b>Lead Instructor:</b> 
<br><b>Certified Instructors:</b> 
    {% for instructor in product.instructors %}
        {{instructor.name}}&nbsp;
    {% endfor %} 


{% endblock %}`enter code here`

これは、データベースに値を入れるために実行しているコードです。

#!flask/bin/python
from app import db, models

instruct1 = models.Instructor(name="instructor1")
db.session.add(instruct1)
db.session.commit()

instruct2 = models.Instructor(name="instructor2")
db.session.add(instruct2)
db.session.commit()

dev = models.Instructor(name="developer")
db.session.add(dev)
db.session.commit()

prod = models.Product(courseName = "test")

prod.instructors = [instruct1]
prod.instructors.append(instruct2)

prod.developer = [dev]

print "Instructors:"
for instructor in prod.instructors:
    print instructor.name

print "Developer"
for i in prod.developer:
    print i.name

db.session.add(prod)
db.session.commit()

そしてここに出力があります:

Instructors:
instructor1
instructor2
Developer
developer

しかし、Webページを表示すると、次のように表示されます。

Course Name: test 
Curriculum developer: instructor1 instructor2 developer 
Lead Instructor: 
Certified Instructors: instructor1  instructor2  developer 

更新:doobehに感謝します!コードhttp://bpaste.net/show/o8PtsY3Kvu8bxKnDEo24/を更新しましたが、Pythonコードを実行すると、「関係'Product.instructors'でbackref'製品'の作成中にエラーが発生しました:その名前のプロパティがマッパーに存在します」というエラーが表示されます。 'マッパー|インストラクター|インストラクター'

4

1 に答える 1

3

開発者との関係を正しく作成すれば、問題は解消されるようです。現時点では、使用している多対多の関係から関係をコピーしました。したがって、開発者はインストラクターと同じスタックに追加されます。すぐに表示されない理由は、リストを再度印刷するまでデータベースにコミットしていないためです。これらのリストをデータベースにコミットし、再クエリするとすぐに、テンプレートに表示されている倍数が取得されます。

Productモデルを次のように変更した場合は、次のようになります。

class Product(db.Model):
    id = db.Column(db.Integer, primary_key = True)
    courseName = db.Column(db.String(64))

    developer_id = db.Column(db.Integer, db.ForeignKey='instructor.id'))
    developer = db.relationship('Instructor', backref='develops')

    instructors = db.relationship('Instructor', secondary=instructors,
        backref=db.backref('products', lazy='dynamic'))

    def __repr__(self):
        return '<Category> %r>' % (self.courseName)

期待どおりに機能します(テストされていないコード!)。現在、それぞれに1人の開発者しか格納してProductいないため、これらの値を繰り返し処理したり、リストを渡したり、追加するときに追加したりする必要はありません。

同じフィールドを使用して複数の多対多の結合を作成できない理由を明確にするために、SQLレベルで何が起こっているかを分析してみましょう。

M2M結合テーブルinstructorsには2つのフィールドとがinstructor_idあり product_idます。次に、3人のインストラクターを作成します。

id:1    instructor1
id:2    instructor2
id:3    developer

次に、製品を作成します。

id:1    product

これらの最初の2人のインストラクターをその製品に追加すると、instructors リンクテーブルには次のような情報が格納されます。

product_id      instructor_id
1               1
1               2

次に、開発者を同じテーブルに追加します。

product_id      instructor_id
1               1
1               2
1               3

したがって、「この製品のすべてのインストラクターを教えてください」と言うと、SQLAlchemyはモデルに「ねえ、製品がinstructorsテーブル内のインストラクターにリンクされていることを示す関係があるので、すべてのインストラクターを教えてください。製品IDが1"の場合、もちろん、期待した2つだけでなく、3つの結果が得られます。また、同じリンケージを使用しているため、開発者に依頼すると同じ3つの結果が得られます。

2つの多対多の結合を作成する場合は、developersその関係に関連する情報のみを保持する、または同様の2番目のリンクテーブルを作成する必要があります。ただし、この場合、1人の開発者を製品にリンクさせたいだけなので、単純なものを使用しForeignKeyてその関係をマップできます。

于 2013-02-14T21:56:42.767 に答える