SQLAlchemy无法找到与非特权用户的外键关系

时间:2011-02-17 08:16:34

标签: postgresql inheritance permissions sqlalchemy autoload

我在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_paymentpayments_foopayment都是GRANT ed SELECTUPDATE。我已经尝试暂时授予他们所有权限,但没有任何成功。如果这很重要,则payments_payment_id_seqGRANT的{​​{1}}版本为SELECT。显然,USAGE的架构fooGRANT

我应该如何在Python中手动定义关系,或者在DB端执行某些操作,那么内省是否适用于非特权用户?

调试问题的提示也非常受欢迎,因为我在SA内部完全迷失了。

1 个答案:

答案 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')