我在PostgreSQL 8.4数据库中有一个Django创建的表,其中一个表“扩展”另一个表。一个表(FooPayment
)具有主键,它引用另一个表(Payment
)。在SQL中它看起来像这样:
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
一起安装):< / p>
# 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_payment
和payments_foopayment
都是GRANT
ed SELECT
和UPDATE
。我已经尝试暂时授予他们所有权限,但没有任何成功。如果这很重要,则payments_payment_id_seq
和GRANT
的{{1}}版本为SELECT
。显然,USAGE
的架构foo
为GRANT
。
我应该如何在Python中手动定义关系,或者在DB端执行某些操作,那么内省是否适用于非特权用户?
调试问题的提示也非常受欢迎,因为我在SA内部完全迷失了。
答案 0 :(得分: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
。
如果autoload的权限让你感到悲伤,你可以在代码中声明这样的关系:
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')