金字塔控制台脚本 - DBSession没有插入?

时间:2013-10-07 03:28:51

标签: sqlalchemy pyramid

我有一个基于SQLAlchemy脚手架的Pyramid Web应用程序。在我的应用程序中,我有一个函数,通过SQLAlchemy在我的数据库中发送电子邮件和插入/更新表。在网络上,我通过视图调用此函数,即Web上的按钮提交到视图,并在视图中调用该函数。

我想创建一个调用同一函数的控制台脚本,但是要按计划调用。我正在处理setting up a Pyramid console script的示例文档。在一个完美的世界中,我希望能够访问我在我的Web应用程序中使用的所有模型和功能,但能够从控制台使用它们。通过反复试验,我已经成功地包含了一些基础知识,以便我可以查询我的一个模型对象并将其打印到控制台。我甚至可以调用我想要的功能。

但是,在函数内部,它会向数据库写入一行并发送一封电子邮件。当我从控制台调用该功能时,它完成所有工作(至少打印到控制台)并发送电子邮件。它打印'INSERT'语句应该在哪里。但实际上它不是执行INSERT或提交它们,我不确定是哪一个。我正在从我的models.py包中导入DBSession,金字塔应用程序的其余部分使用它,但有一个技巧或我需要知道的东西?我尝试声明一个新的DBSession并将其自定义为控制台脚本,但是却出现了某种“无法找到映射器”的错误。

在下面的示例中,为每条记录调用SendEmail;函数本身基本上查找相应的记录,将一行返回到数据库中以获取另一个模型对象,然后发送电子邮件。它作为Web应用程序的一部分非常有用。在这里的控制台端,它打印出它正在做它应该做的所有事情并发送电子邮件,但实际上没有插入数据库记录。

这是我的控制台脚本:

# describe the script here

import datetime
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import logging
import optparse
import smtplib
from smtplib import SMTPException
import sys
import textwrap

import pyramid.paster
from pyramid.paster import bootstrap
from pyramid.request import Request

from sqlalchemy.exc import DBAPIError
from sqlalchemy import (
    or_,
    and_,
    not_,
    asc,
    desc,
    func
    )

from functions import SendEmail
from models import DBSession, LogSession, groupfinder

from models import MyObject

from pyramid.session import UnencryptedCookieSessionFactoryConfig

my_session_factory = UnencryptedCookieSessionFactoryConfig('itsaseekreet')

from pyramid.config import Configurator

from sqlalchemy import engine_from_config

from pyramid.authentication import AuthTktAuthenticationPolicy
from pyramid.authorization import ACLAuthorizationPolicy

from zope.sqlalchemy import ZopeTransactionExtension


def main():
    description = """\
        Print the deployment settings for a Pyramid application.  Example:
        'show_settings deployment.ini'
        """
    usage = "usage: %prog config_uri"
    parser = optparse.OptionParser(
        usage=usage,
        description=textwrap.dedent(description)
    )
    parser.add_option(
        '-o', '--omit',
        dest='omit',
        metavar='PREFIX',
        type='string',
        action='append',
        help=("Omit settings which start with PREFIX (you can use this "
              "option multiple times)")
    )
    options, args = parser.parse_args(sys.argv[1:])
    if not len(args) >= 1:
        print('You must provide at least one argument')
        return 2
    config_uri = args[0]
    omit = options.omit
    if omit is None:
        omit = []

    request = Request.blank('/', base_url='http://localhost:13715/')
    env = bootstrap(config_uri, request=request)
    settings = env['registry'].settings
    pyramid.paster.setup_logging(config_uri)

    engine = engine_from_config(settings, 'sqlalchemy.')
    DBSession.configure(bind=engine)
    LogSession.configure(bind=engine)
    authn_policy = AuthTktAuthenticationPolicy(
        'itsaseekreet', callback=groupfinder)
    authz_policy = ACLAuthorizationPolicy()
    config = Configurator(settings=settings,
                          root_factory='myapp.models.RootFactory',
                          session_factory=my_session_factory)
    config.set_authentication_policy(authn_policy)
    config.set_authorization_policy(authz_policy)
    config.add_static_view('static', 'static', cache_max_age=3600)

    log = logging.getLogger(__name__)

    log.info('Starting EmailSender...')

    init_time = datetime.datetime.utcnow()

    log.info('Current datetime (UTC): {0}'.format(str(init_time)))

    items_to_process = DBSession.query(MyObject). \
        filter(and_(MyObject.startdate <= init_time,
                    MyObject.enddate >= init_time,
                    MyObject.manual_send_only == False)).all()


    for item in items_to_process:
        log.info('{0}: runtime: {1}'.format(item.description, item.send_time))
        item_url = request.route_url('itemresponse', responseid='XXXXXX')

        rtn = SendEmail(item.id, item_url)

    env['closer']()


if __name__ == '__main__':
    main()

另外,我正在遇到另一件事,但现在不是那么重要:我有log -blah进入数据库的日志处理程序(使用我创建的LogSession)。这也适用于Web应用程序,但在运行时不会写入数据库。我不知道它是否是同一个问题,或者如果在我的配置中,处理程序没有设置为控制台或其他东西。我不知道,但上面的主要问题是我正在寻找的。谢谢!

编辑: 我对它进行了更多搜索并发现了the tutorial talking about SQLAlchemy setup并且正在查看initializedb.py脚本,因为它会像我想要的那样修改数据库并连接到模型。我做了import transaction并用

包装上面的内容
with transaction.manager:
    items_to_process = DBSession.query(MyObject). \
        filter(and_(MyObject.startdate <= init_time,
                    MyObject.enddate >= init_time,
                    MyObject.manual_send_only == False)).all()


    for item in items_to_process:
        log.info('{0}: runtime: {1}'.format(item.description, item.send_time))
        item_url = request.route_url('itemresponse', responseid='XXXXXX')

        rtn = SendEmail(item.id, item_url)

这似乎完全符合我的要求,或者至少实际上是提交和写入数据库。我将不得不继续使用它,因为我不确定如果在被调用函数中存在数据库错误,如果它将整个事情卷回来,如果它提交了部分内容,或者是什么,那么会发生什么。在函数本身内有异常处理和清理,但我认为它通常取决于pyramid_tm和Zope来处理幕后的东西。

1 个答案:

答案 0 :(得分:0)

据我所知,你永远不会做出改变。

DBSession.commit()

closer功能之前调用它。它应该根据您使用DBSession的方式工作。