2014-12-04 17 views
6

Tôi đang cố gắng để hiểu làm thế nào để làm tham gia với các phím tổng hợp nước ngoài trên SQLAlchemy và nỗ lực của tôi để làm điều này là không.SQLAlchemy tham gia với các khóa ngoài tổng hợp (với bình phương sqlalchemy)

Tôi có các lớp mô hình sau đây về mô hình đồ chơi của tôi (Tôi đang sử dụng Flask-SQLAlchemy, nhưng tôi không chắc chắn điều này có bất cứ điều gì để làm với các vấn đề):

# coding=utf-8 
from flask import Flask 
from flask.ext.sqlalchemy import SQLAlchemy 

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


class Asset(db.Model): 
    __tablename__ = 'asset' 
    user = db.Column('usuario', db.Integer, primary_key=True) 
    profile = db.Column('perfil', db.Integer, primary_key=True) 
    name = db.Column('nome', db.Unicode(255)) 

    def __str__(self): 
     return u"Asset({}, {}, {})".format(self.user, self.profile, self.name).encode('utf-8') 


class Zabumba(db.Model): 
    __tablename__ = 'zabumba' 

    db.ForeignKeyConstraint(
     ['asset.user', 'asset.profile'], 
     ['zabumba.user', 'zabumba.profile'] 
    ) 

    user = db.Column('usuario', db.Integer, primary_key=True) 
    profile = db.Column('perfil', db.Integer, primary_key=True) 
    count = db.Column('qtdade', db.Integer) 

    def __str__(self): 
     return u"Zabumba({}, {}, {})".format(self.user, self.profile, self.count).encode('utf-8') 

sau đó tôi dân sự cơ sở dữ liệu với một số dữ liệu giả:

db.drop_all() 
db.create_all() 

db.session.add(Asset(user=1, profile=1, name=u"Pafúncio")) 
db.session.add(Asset(user=1, profile=2, name=u"Skavurska")) 
db.session.add(Asset(user=2, profile=1, name=u"Ermengarda")) 

db.session.add(Zabumba(user=1, profile=1, count=10)) 
db.session.add(Zabumba(user=1, profile=2, count=11)) 
db.session.add(Zabumba(user=2, profile=1, count=12)) 

db.session.commit() 

Và thử các truy vấn sau đây:

> for asset, zabumba in db.session.query(Zabumba).join(Asset).all(): 
>  print "{:25}\t<---->\t{:25}".format(asset, zabumba) 

B ut SQLAlchemy nói với tôi rằng nó không thể tìm thấy chìa khóa nước ngoài đầy đủ cho gia này:

Traceback (most recent call last): 
    File "sqlalchemy_join.py", line 65, in <module> 
    for asset, zabumba in db.session.query(Zabumba).join(Asset).all(): 
    File "/home/calsaverini/.virtualenvs/recsys/local/lib/python2.7/site-packages/sqlalchemy/orm/query.py", line 1724, in join 
    from_joinpoint=from_joinpoint) 
    File "<string>", line 2, in _join 
    File "/home/calsaverini/.virtualenvs/recsys/local/lib/python2.7/site-packages/sqlalchemy/orm/base.py", line 191, in generate 
    fn(self, *args[1:], **kw) 
    File "/home/calsaverini/.virtualenvs/recsys/local/lib/python2.7/site-packages/sqlalchemy/orm/query.py", line 1858, in _join 
    outerjoin, create_aliases, prop) 
    File "/home/calsaverini/.virtualenvs/recsys/local/lib/python2.7/site-packages/sqlalchemy/orm/query.py", line 1928, in _join_left_to_right 
    self._join_to_left(l_info, left, right, onclause, outerjoin) 
    File "/home/calsaverini/.virtualenvs/recsys/local/lib/python2.7/site-packages/sqlalchemy/orm/query.py", line 2056, in _join_to_left 
    "Tried joining to %s, but got: %s" % (right, ae)) 
sqlalchemy.exc.InvalidRequestError: Could not find a FROM clause to join from. Tried joining to <class '__main__.Asset'>, but got: Can't find any foreign key relationships between 'zabumba' and 'asset'. 

Tôi đã thử một số thứ khác như: tuyên bố ForeignKeyConstraint trên cả hai bảng hoặc đảo ngược các truy vấn để db.session.query(Asset).join(Zabumba).all().

Tôi đang làm gì sai?

Cảm ơn.


PS: Trong mã ứng dụng thực tế của tôi vấn đề là thực sự là một chút phức tạp hơn bởi vì những bảng đang trên lược đồ khác nhau và tôi sẽ sử dụng điều ràng buộc:

app.config['SQLALCHEMY_BINDS'] = { 
    'assets':  'mysql+mysqldb://fooserver/assets', 
    'zabumbas':  'mysql+mysqldb://fooserver/zabumbas', 
} 

Và rồi tôi sẽ khai báo các ràng buộc khác nhau trên các bảng. Làm thế nào tôi nên khai báo ForeignKeyConstraint sau đó?

Trả lời

5

Mã của bạn có ít lỗi chính tả, điều chỉnh sẽ làm cho toàn bộ mã hoạt động.

Xác định đúng ForeignKeyConstraint:

  • nó không phải là chỉ cần định nghĩa nó, bạn cần phải thêm nó vào __table_args__
  • định nghĩa của cộtrefcolumns thông số bị đảo ngược (xem documentation)
  • tên của các cột phải là tên trong cơ sở dữ liệu chứ không phải tên của các thuộc tính ORM

như trong đoạn mã sau:

class Zabumba(db.Model): 
    __tablename__ = 'zabumba' 

    __table_args__ = (
     db.ForeignKeyConstraint(
      ['usuario', 'perfil'], 
      ['asset.usuario', 'asset.perfil'], 
     ), 
    ) 

xây dựng đúng cách truy vấn bằng cách cả hai lớp trong mệnh đề truy vấn:

for asset, zabumba in db.session.query(Asset, Zabumba).join(Zabumba).all(): 
     print "{:25}\t<---->\t{:25}".format(asset, zabumba) 
Các vấn đề liên quan