3

私は、flask-sqlalchemy で多対多の関係を適切に実装するのに非常に苦労しました。タグの重複から始まり、何日も経った今、マッピングの問題が発生しています。公正な警告ですが、これらの問題が発生する前は、私のコードははるかにきれいでした。テストを高速化するために addproduct.py ファイルも追加しました。だからここにあります。

models.py

1 from app import app, db                                                                                                                                     
2 
3 product_tags = db.Table('association',
4         db.Column('product_id', db.Integer, db.ForeignKey('product.id')),
5         db.Column('tag_name', db.Integer, db.ForeignKey('tag.name'))
6 )
7 
8 class Product(db.Model):                                                                                                                                    
9     id = db.Column(db.Integer, primary_key=True)
10     title = db.Column(db.String(128))                                                                                                                       
11     description = db.Column(db.Text)
12     image = db.Column(db.String(64))
13     link = db.Column(db.String(256))
14     price = db.Column(db.Float())
15     timestamp = db.Column(db.DateTime)                                                                                                                      
16     expiration = db.Column(db.String(6))
17     tags = db.relationship('Tag', secondary=product_tags,                                                                                                   
18             backref=db.backref('product', lazy='dynamic'))
19 
20     def __init__(self, title, description, image, link, price, timestamp, expiration,    tags):                                                                
21         self.title = title                                                                                                                                  
22         self.description = description                                                                                                                      
23         self.image = image                                                                                                                                  
24         self.link = link                                                                                                                                    
25         self.price = price                                                                                                                                  
26         self.timestamp = timestamp
27         self.expiration = expiration                                                                                                                        
28         self.tags = tags                                                                                                                                    
29         print self.title                                                                                                                                    
30 
31     def __repr__(self):                                                                                                                                     
32         return '<Title %r, Description %r, Image %r, Link %r, Price %r, Timestamp %r,    Expires %r, Tags %r>' % (self.title, self.description, self.image, sel
33 
34 class Tag(db.Model):                                                                                                                                        
35     name = db.Column(db.String(32), primary_key=True)
36 
37     def __init__(self, name):
38         self.name = name                                                                                                                                    
39 
40     def __repr__(self):                                                                                                                                     
41         return '<Tag %r>' % self.name

addproduct.py

1 from app import db                                                                                                                                          
2 from app.models import Product, Tag, product_tags
3 from datetime import datetime                                                                                                                               
4 
5 imagefolder = 'static/img/'
6 
7 title = 'product'
8 description = 'description'
9 image = 'image.jpg'
10 link = 'http://link.com'
11 price = 2000.00
12 expiration = ''
13 tags = ['tag1','tag2']                                                                                                                              
14 
15 newtags = []                                                                                                                                                
16 
17 def create_product(title, description, image, link, price, expiration, tags):                                                                               
18     image = imagefolder + image                                                                                                                             
19     tag_assoc = []
20     for tag in tags:                                                                                                                                        
21         tagcheck = Tag.query.filter_by(name=tag).first()                                                                                                    
22         if tagcheck == None:                                                                                                                                
23             tag_assoc.append(Tag(tag))                                                                                                                      
24         else:                                                                                                                                               
25             newtags.append(tag)                                                                                                                             
26 
27     product = Product(title, description, image, link, price, datetime.utcnow(),    expiration, tag_assoc)                                                     
28     create_assoc(newtags)                                                                                                                                   
29     return product                                                                                                                                          
30 
31 def create_assoc(newtags):                                                                                                                                  
32     title_search = Product.query.filter_by(title=title).first()                                                                                             
33     for tag in newtags:
34         assoc = product_tags.insert().values(product_id=title_search.id,    tag_name=tag)
35         db.session.add(assoc)                                                                                                                               
36     db.session.commit()
37 
38 if __name__ == '__main__':
39     product = create_product(title, description, image, link, price, expiration,    tags)
40     db.session.add(product)                                                                                                                                 
41     db.session.commit()                                                                                                                                     
42     create_assoc(newtags) 

私が得るエラーメッセージは次のとおりです。

11:11 ~/shop $ python addproduct.py
product
Traceback (most recent call last):
File "addproduct.py", line 39, in <module>
product = create_product(title, description, image, link, price, expiration, tags)
File "addproduct.py", line 28, in create_product
create_assoc(newtags)
File "addproduct.py", line 35, in create_assoc
db.session.add(assoc)
File "/home/username/.local/lib/python2.7/site-packages/sqlalchemy/orm/scoping.py", line 114, in do
return getattr(self.registry(), name)(*args, **kwargs)
File "/home/username/.local/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 1358, in add
raise exc.UnmappedInstanceError(instance)
sqlalchemy.orm.exc.UnmappedInstanceError: Class 'sqlalchemy.sql.expression.Insert' is not mapped

これは、チュートリアルから直接ではなく、私の最初の webapp であり、完全に迷っています。助けてください!

4

1 に答える 1

6

あなたのモデルの最初の間違いは、あなたの関連付けには正しく 2 つの外部キーがありますが、タグの外部キーは ですが、クラスInteger内の主キーはです。それらは一致するはずです。それとは別に、モデルはよく見えます。TagString

create_productまた、関数を単純化できるはずです。

def create_product(title, description, image, link, price, expiration, tags):
    image = imagefolder + image
    tag_list = []
    for tag in tags:
        tagcheck = Tag.query.filter_by(name=tag).first()
        if tagcheck is None:
            tag_list.append(Tag(tag))
        else:
            tag_list.append(tagcheck)
    product = Product(title, description, image, link, price, datetime.utcnow(), expiration, tag_list)
    return product

__init___これは、コンストラクター内で簡単に移動できます。あなたの例では、関連付けテーブルを直接扱いますが、まったくする必要はありません.ORMが正しいことをすることを信頼するだけです。それがSQLAlchemyの美しさです。

製品モデルがどのように見えるかの例を次に示します。

class Product(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(128))
    description = db.Column(db.Text)
    image = db.Column(db.String(64))
    link = db.Column(db.String(256))
    price = db.Column(db.Float())
    timestamp = db.Column(db.DateTime)
    expiration = db.Column(db.String(6))
    tags = db.relationship('Tag', secondary=product_tags,
            backref=db.backref('products', lazy='dynamic'))

    def __init__(self, title, description, image, link, price, timestamp, expiration, tags):
        self.title = title
        self.description = description
        self.image = image
        self.link = link
        self.price = price
        self.timestamp = timestamp
        self.expiration = expiration

        for tag in tags:
            tagcheck = Tag.query.filter_by(name=tag).first()
            if tagcheck is None:
                self.tags.append(Tag(tag))
            else:
                self.tags.append(tagcheck)

    def __repr__(self):
        return '<{}, {}>'.format(self.title, ":".join([x.name for x in self.tags]))

テストするために、最初にいくつかのタグをシステムに追加します。

ta = Tag('cat')
tb = Tag('dog')
db.session.add_all([ta, tb])
db.session.commit()

>>> Tag.query.all()
[<Tag u'cat'>, <Tag u'dog'>]

これらのタグを使用する商品と、新しいタグを追加してみましょう。

p = Product(
    'title',
    'description',
    'image',
    'link',
    0.0,
    datetime.now(),
    'expiry',
    ['dog','cat','horse']
)
db.session.add(p)
db.session.commit()

その製品を作成するとき、コンストラクターはこれら 3 つの文字列タグのそれぞれを受け取り、「ねえ、この名前のタグは既に存在しますか?」と言います。存在する場合はそれを使用し、存在しない場合はその名前で新しいタグを作成します。SQLAlchemy は、新しいタグをセッションに追加し、製品がコミットされたときにそれをコミットすることを知っているほど賢いです。

>>> Tag.query.all()
[<Tag u'cat'>, <Tag u'dog'>, <Tag u'horse'>]

次に、ドッグタグが付いたすべての製品を検索してみましょう (さらに製品が追加されていると仮定します)。

>>> tag = Tag.query.get('dog')
>>> products = tag.products
>>> [x.title for x in products]
['title','other','examples']

繰り返しますが、関連付けテーブルにまったく触れていないので、その必要はありません。SQLAlchemy は私たちの労力を節約してくれます。

于 2013-06-24T20:31:06.953 に答える