简体   繁体   English

金字塔,sqlalchemy dbsession

[英]Pyramid, sqlalchemy dbsession

When building a Pyramid app (SQLAlchemy as ORM) I'm hit with a problem I can't seem to figure out. 在构建Pyramid应用程序(SQLAlchemy为ORM)时,我遇到了一个我似乎无法弄清的问题。
Project built with SQLAlchemy scaffold, so all the setup is proper. 使用SQLAlchemy支架构建的项目,因此所有设置均正确。
When I use DBSession variable in views or like it works properly. 当我在视图中使用DBSession变量或类似它正常工作时。
Example : 范例:

from pabsite.models import DBSession
....
@view_config(route_name='admin_class', renderer='admin_class.mako')
def admin_class(request):
    db_class = eval(request.matchdict['db_class'])
    class_objects = DBSession.query(db_class).all()
    return {'db_class':db_class, 'class_objects':class_objects, "db_class_name":request.matchdict['db_class']}

Now the problem arises when I try to create a new, non-SQLAlchemy class like : 现在,当我尝试创建一个新的非SQLAlchemy类时,就会出现问题:

from pabsite.models import DBSession
.....
class AdminPost(colander.MappingSchema):
    tester = DBSession.query(Post).all()
    title = colander.SchemaNode(colander.String(),
                                       validator=colander.Length(max=100),
                                       widget = get_inputbox(),
                                       description='Tytuł')

The moment I want to run the app I'm hit with : 我想运行遇到的应用程序的那一刻:

  File "/media/stuff/Projects/current/web/PabsiteProject/pabsite/pabsite/__init__.py", line 1, in <module>
    from pabsite.admin.views import admin_routes
  File "/media/stuff/Projects/current/web/PabsiteProject/pabsite/pabsite/admin/views.py", line 9, in <module>
    from models import getAdminPost
  File "/media/stuff/Projects/current/web/PabsiteProject/pabsite/pabsite/admin/models.py", line 13, in <module>
    class AdminPost(colander.MappingSchema, Base):
  File "/media/stuff/Projects/current/web/PabsiteProject/pabsite/pabsite/admin/models.py", line 14, in AdminPost
    tester = DBSession.query(Post).all()
.....
sqlalchemy.exc.UnboundExecutionError: Could not locate a bind configured on mapper Mapper|Post|posts, SQL expression or this Session

It must be something trivial but I can't seem to make that class aware of the DBSession binding. 它一定有些琐碎,但我似乎无法使该类意识到DBSession绑定。 Can somebody please point me to some solution / docs. 有人可以给我指出一些解决方案/文档。

EDIT : Sorry, I've posted a stupid example which I've ended up when trying different things. 编辑 :对不起,我发布了一个愚蠢的例子,当我尝试不同的事情时,我最终将其结束。
Proper example : 正确的例子:

class AdminPost(colander.MappingSchema):
    title = colander.SchemaNode(colander.String(),
                                       validator=colander.Length(max=10),
                                       widget = get_inputbox(),
                                       description='Tytuł')
    category = colander.SchemaNode(colander.String(),
                                       widget = get_select_widget(),
                                       description='Kategoria')

    def getForm(self):
        schema = self
        admin_form = Form(schema, buttons=('submit',))
        return admin_form

Now I define the select widget (I want them to be reused in other classes) as : 现在,我将select小部件(我希望它们在其他类中重用)定义为:

def get_select_widget():
    get_categories = DBSession.query(Category).all()
    select_widget = deform.widget.SelectWidget(values=get_categories())

And here get_categories throws the error I mentioned earlier. 在这里,get_categories引发了我前面提到的错误。 It maybe my misconception of using Python, but I don't know how to get DBSession be aware of the app engine configuration. 这也许是我对使用Python的误解,但我不知道如何让DBSession了解应用程序引擎的配置。
EDIT 2 Category is a db model while AdminPost class server as a deform model. 编辑2类别是db模型,而AdminPost类服务器是变形模型。 Here's the def 这是国防部

class Category(Base):
    __tablename__ = 'categories'
    id = Column(Integer, primary_key=True)
    name = Column(String(150))
    slug = Column(String(150))
    name_en = Column(String(150))
    slug_en = Column(String(150))

    def __init__(self,name=''):
        self.name = name

    def __repr__(self):
        return self.name

How can they share the same parent as they're meant for different things. 他们如何共享同一个父母,因为他们的本意是不同的事情。

EDIT 4 编辑4

DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
Base = declarative_base()

They're defined as the pyramid scaffold makes them - in models.py in app root. 它们被定义为金字塔脚手架制造的-在应用程序根目录的models.py中。 That's where I import them from, and they do work, but in views, not in a class which I prepared on deform. 那是我从中导入它们的地方,并且它们确实起作用,但是从视图的角度来看,而不是在我准备好进行变形的课程中。

Your problem lies with the way python works and what you are trying to achieve here. 您的问题在于python的工作方式以及您要在此处实现的目标。 I assume you want AdminPost.tester to always contain an up-to-date list of all items in the Post table? 我假设您希望AdminPost.tester始终包含Post表中所有项目的最新列表?

Let's address the problems one-by-one. 让我们一一解决这些问题。 First, the statement 一,声明

class AdminPost(colander.MappingSchema):
    tester = DBSession.query(Post).all()

will be executed at import time. 将在导入时执行。 Check this out: 看一下这个:

print "Before import"
import some_module
print "After import"
some_module.SomeClass()

And let some_module look like this: 并让some_module看起来像这样:

class A(object):
    print "Inside A"
    def __init__(self):
        print "New instance of A"

This is the output you will get: 这是您将获得的输出:

Before import
Inside A
After import
New instance of A

The reason for this is the way python parses the code: It executes each of the statements it finds, but on encountering a def it will not evaluate anything that is indented. 这样做的原因是python解析代码的方式:它执行找到的每个语句,但是遇到def它不会评估缩进的任何内容。 (This is a rough description!) (这是一个粗略的描述!)

So now that you have seen this, you know that your query is executed (most likely) when you start your program. 因此,既然您已经看到了这一点,就可以知道(最有可能)在启动程序时执行查询。 At this point, sqlalchemy has not found all its tables and made the configuration for it. 此时,sqlalchemy尚未找到其所有表并进行了配置。 Furthermore, you most likely don't have an engine bound yet. 此外,您很可能还没有引擎绑定。

But your problem actually isn't really SQLAlchemy related. 但是您的问题实际上与SQLAlchemy无关。 It is a common misconception of how to define values that every instance of a class should as a default. 对于如何定义类的每个实例应默认设置的值,这是一个普遍的误解。 In Python you do this inside an __init__ : 在Python中,您可以在__init__内部执行此操作:

class AdminPost(colander.MappingSchema):
    def __init__(self, *args, **kwargs):
        tester = DBSession.query(Post).all()
        colander.MappingSchema.__init__(self, *args, **kwargs)

The last line makes sure the default constructor is called afterwards. 最后一行确保随后会调用默认构造函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM