2011-02-17 65 views
1

我在PostgreSQL 8.4數據庫中有一個Django創建的表,其中一個表「擴展」另一個表。一個表(FooPayment)具有主鍵,該主鍵引用另一個表(Payment)。在SQL它看起來像這樣:SQLAlchemy無法找到與非特權用戶的外鍵關係

CREATE TABLE foo.payments_payment 
(
    id integer NOT NULL DEFAULT nextval('payments_payment_id_seq'::regclass), 
    user_id integer NOT NULL, 
    ... 
    CONSTRAINT payments_payment_pkey PRIMARY KEY (id), 
    CONSTRAINT payments_payment_user_id_fkey FOREIGN KEY (user_id) 
     REFERENCES auth.auth_user (id) MATCH SIMPLE 
     ON UPDATE NO ACTION ON DELETE NO ACTION DEFERRABLE INITIALLY DEFERRED 
) 

CREATE TABLE foo.payments_foopayment 
(
    payment_ptr_id integer NOT NULL, 
    ... 
    CONSTRAINT payments_foopayment_pkey PRIMARY KEY (payment_ptr_id), 
    CONSTRAINT payments_foopayment_payment_ptr_id_fkey FOREIGN KEY (payment_ptr_id) 
     REFERENCES foo.payments_payment (id) MATCH SIMPLE 
     ON UPDATE NO ACTION ON DELETE NO ACTION DEFERRABLE INITIALLY DEFERRED, 
    ... 
) 

不過,我還沒有使用Django ORM由於種種原因,我試圖訪問從SQLAlchemy的表(我使用的版本0.6.6,如與pip安裝):

# Base = declarative_base() 
... 

class Payment(Base): 
    __tablename__ = 'payments_payment' 
    __table_args__ = {'schema': 'foo', 'autoload': True} 
    user = relation(User, backref='payments') 

class FooPayment(Payment): 
    __tablename__ = 'payments_foopayment' 
    __table_args__ = {'schema': 'foo', 'autoload': True} 

當我這樣做是超級用戶,一切正常。當我連接爲低權限的用戶我得到一個異常:

Traceback (most recent call last): 
    File "./test.py", line 3, in <module> 
    from foos import models 
    File "./foos/models.py", line 127, in <module> 
    class FooPayment(Payment): 
    File "lib/python2.6/site-packages/sqlalchemy/ext/declarative.py", line 1167, in __init__ 
    _as_declarative(cls, classname, cls.__dict__) 
    File "lib/python2.6/site-packages/sqlalchemy/ext/declarative.py", line 1099, in _as_declarative 
    ignore_nonexistent_tables=True) 
    File "lib/python2.6/site-packages/sqlalchemy/sql/util.py", line 260, in join_condition 
    "between '%s' and '%s'.%s" % (a.description, b.description, hint)) 
sqlalchemy.exc.ArgumentError: Can't find any foreign key relationships between 'payments_payment' and 'payments_foopayment'. 

當我連接與PgAdmin3這個低權限用戶,我看到在GUI的關係。我也可以用這個說法看出來,SQLAlchemy的問題本身:

SELECT conname, pg_catalog.pg_get_constraintdef(oid, true) as condef 
    FROM pg_catalog.pg_constraint r 
    WHERE r.conrelid = 16234 AND r.contype = 'f' 
    ORDER BY 1 

哪個正確返回一行,含

"payments_foopayment_payment_ptr_id_fkey"; "FOREIGN KEY (payment_ptr_id) REFERENCES payments_payment(id) DEFERRABLE INITIALLY DEFERRED" 

至於數據庫的權限,無論是payments_paymentpayments_foopaymentGRANTSELECTUPDATE。我已經暫時授予他們所有權限,沒有任何成功。如果這很重要,則的GRANT編號爲SELECTUSAGE。顯然,模式fooGRANT編輯爲USAGE

我應該如何在Python中手動定義關係,或者在數據庫端做一些事情,這樣內省會對非特權用戶起作用?

調試問題的提示也非常受歡迎,因爲我完全迷失在SA內部。

回答

2

您可以記錄SQLAlchemy的查詢,並比較不同用戶發生的情況。

import logging 

# Early in your main() 
logging.basicConfig() 
logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO) 
logging.getLogger('sqlalchemy.orm').setLevel(logging.INFO) 

logging.DEBUG也記錄響應數據。

據我所知,對於反射,SQLAlchemy使用表OID和查詢pg_catalog;你舉了一個例子。代碼在SQLAlchemy.dialects.postgresql.base

如果自動加載的權限給你悲傷,你可以聲明在代碼是這樣的關係:

class FooPayment(Payment): 
    payment_ptr_id = Column(Integer, ForeignKey(Payment.id), primary_key=True) 
    payment = relationship(
        Payment, foreign_keys=[payment_ptr_id], backref='foo_payment') 
+0

非常感謝你。與`echo = True`相比,日誌並沒有真正的信息量(在爲'FooPayment`記錄任何內容之前引發異常),但手動定義有所幫助。不過,因爲我不知道自動加載失敗的原因,我會將問題保留一兩天。 – drdaeman 2011-02-21 13:08:28