如何与SQLAlchemy一起正确使用association_proxy和ordering_list [英] How to properly use association_proxy and ordering_list together with SQLAlchemy

查看:261
本文介绍了如何与SQLAlchemy一起正确使用association_proxy和ordering_list的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基于SQLAlchemy Google Group上的一些帖子:

https://groups.google.com/forum/#!topic/sqlalchemy/S4_8PeRBNJw
https://groups.google.com/forum/#!topic/sqlalchemy/YRyI7ic1QkY



我假设我可以成功使用 assocation_proxy ordering_list 扩展来创建两个模型之间的有序的多对多关系,如下面的Flask / SQLAlchemy代码:

  from flask导入烧瓶
from flask_sqlalchemy从sqlalchemy.ext.associationproxy导入SQLAlchemy
从sqlalchemy.ext.orderinglist导入association_proxy
import ordering_list
$ b app = Flask(__ name__)
app.debug = True
app.config ['SQLALCHEMY_DATABASE_URI'] = 'sqlite://'
db = SQLAlchemy(app)


class Image(d b.Model):
__tablename__ ='images'

id = db.Column(db.Integer,primary_key = True)
filename = db.Column(db.String( 255))


class UserImage(db.Model):
__tablename__ ='user_images'

user_id = db.Column(db.Integer, db.ForeignKey('users.id'),primary_key = True)
image_id = db.Column(db.Integer,db.ForeignKey('images.id'),primary_key = True)
image = db.relationship('Image')
position = db.Column(db.Integer)

$ b $ class User(db.Model):
__tablename__ =users

id = db.Column(db.Integer,primary_key = True)
name = db.Column(db.String(255))

_images = db.relationship('UserImage',
order_by ='UserImage.position',
collection_class = ordering_list('position'))
images = association_proxy('_ images','image')


with app.app_context():
db.create_all()
use r = User(name ='Matt')
user.images.append(Image(filename ='avatar.png'))
db.session.add(user)
db.session .commit()

if __name__ =='__main__':
app.run()

但是我最终得到以下回溯:

$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ Traceback(最近的最后一次调用):
在< module>文件中的app.py,第44行。
user.images.append(Image(filename ='avatar.png'))
文件/Users/matt/.virtualenvs/sqlalchemy-temp/lib/python2.7/site-packages/sqlalchemy /ext/associationproxy.py,第595行,附加
item = self._create(value)
文件/Users/matt/.virtualenvs/sqlalchemy-temp/lib/python2.7/site (2))
返回self.creator(value)
TypeError:__init __()只需要1个参数(2给出)
/ code>

这是不可能的,还是我做了一些明显的错误?

解决方案

sooo close; - )



请阅读创建新值 association_proxy 扩展名。

为了使您的代码正常工作,您可以

Option-1 :添加以下内容构造函数为 UserImage class:



$ p $ def $ __init __(self,image):
self.image = image



Option-2 :用您的函数覆盖默认的创建者

  images = association_proxy('_ images','image',
creator = lambda _i:UserImage(image = _i),

我个人比较喜欢后者。


Based on some posts on the SQLAlchemy Google Group:

https://groups.google.com/forum/#!topic/sqlalchemy/S4_8PeRBNJw https://groups.google.com/forum/#!topic/sqlalchemy/YRyI7ic1QkY

I assumed I could successfully use the assocation_proxy and ordering_list extensions to create an ordered, many to many relationship between two models such as in the following Flask/SQLAlchemy code:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.ext.orderinglist import ordering_list

app = Flask(__name__)
app.debug = True
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite://'
db = SQLAlchemy(app)


class Image(db.Model):
    __tablename__ = 'images'

    id = db.Column(db.Integer, primary_key=True)
    filename = db.Column(db.String(255))


class UserImage(db.Model):
    __tablename__ = 'user_images'

    user_id = db.Column(db.Integer, db.ForeignKey('users.id'), primary_key=True)
    image_id = db.Column(db.Integer, db.ForeignKey('images.id'), primary_key=True)
    image = db.relationship('Image')
    position = db.Column(db.Integer)


class User(db.Model):
    __tablename__ = "users"

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(255))

    _images = db.relationship('UserImage',
        order_by='UserImage.position',
        collection_class=ordering_list('position'))
    images = association_proxy('_images', 'image')


with app.app_context():
    db.create_all()
    user = User(name='Matt')
    user.images.append(Image(filename='avatar.png'))
    db.session.add(user)
    db.session.commit()

if __name__ == '__main__':
    app.run()

But I end up with the following traceback:

$ python app.py
Traceback (most recent call last):
  File "app.py", line 44, in <module>
    user.images.append(Image(filename='avatar.png'))
  File "/Users/matt/.virtualenvs/sqlalchemy-temp/lib/python2.7/site-packages/sqlalchemy/ext/associationproxy.py", line 595, in append
    item = self._create(value)
  File "/Users/matt/.virtualenvs/sqlalchemy-temp/lib/python2.7/site-packages/sqlalchemy/ext/associationproxy.py", line 522, in _create
    return self.creator(value)
TypeError: __init__() takes exactly 1 argument (2 given)

Is this not possible or am I doing something blatantly wrong?

解决方案

sooo close ;-)

Please read Creation of New Values secion of association_proxy extension.
In order to make your code work, you can either

Option-1: add the following constructor to UserImage class:

def __init__(self, image):
    self.image = image

or

Option-2: override the default creator with your function:

images = association_proxy('_images', 'image',
    creator=lambda _i: UserImage(image=_i),
    )

I personally favor the latter.

这篇关于如何与SQLAlchemy一起正确使用association_proxy和ordering_list的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆