【问题标题】:Web2py SQLFORM update or insert depending on record existence checked at callbackWeb2py SQLFORM 更新或插入取决于在回调中检查的记录存在
【发布时间】:2015-08-26 12:12:21
【问题描述】:

我遇到了以下挑战。

我可以使用回调函数来决定是更新记录还是在 form.process() 调用中插入新记录?

简单地说,我需要一个 SQLFORM,用户将使用文本引用标识符和可选的要上传的文件来填充它。也就是说,他们应该能够上传带有引用的文件,或者只是插入一个新引用并稍后添加其文件通过相同的 SQLFORM。

型号:

db.define_table('t_object_occurence',
    Field('f_refid', type='string', label=T('Reference')),
    Field('f_object_id', db.t_object, label=T('Object')),
    Field('f_temp_file', type='upload', label=T('File'), autodelete=True)
    #more fileds
)

每当用户选择一个文件时,一些 jQuery 会根据文件名(正式定义)更新 ref id 字段。

查看:

{{if auth.has_permission('Object_occurence_UL'):}}
<h2>Add a new occurence</h2>
    {{=upload_form}}
{{pass}}
<h2>Latest occurences</h2>
{{=grid}}
<!-- some jQuery -->

然后,通过 form.process() 调用的回调函数执行以下检查(以及其他检查范围之外的检查):

  1. 如果不存在具有相同 ref id 的记录,则此表单必须生成 db insert。有或没有上传的文件。
  2. 如果是这样,主要有两种情况:
    1. 现有记录已经上传文件,然后应该引发表单错误 => 完成
    2. 或者,如果此记录没有其文件,那么我希望它通过上传归档的文件进行更新。

控制器:

def object_browse():
    obj = db.t_object(request.args[0])
    upload_form = SQLFORM(db.t_object_occurence, fields=['f_refid', 'f_temp_file'])
    # recall object ID in form parameters
    upload_form.vars.f_object_id = long(request.args[0])
    # perform field values checks with specific function analyse_occurence_data()
    if upload_form.process(onvalidation=analyse_occurence_data).accepted:
        if upload_form.vars.f_temp_file != '':
            response.flash = "File upload OK, occurence " + str(upload_form.vars.f_refid) + " added to repository"
        else:
            response.flash = "New forcasted occurence added " + str(upload_form.vars.f_refid)
        redirect(URL('object_browse', args=[str(obj.id)], user_signature=True))
    # display occurence list
    query = (db.t_object_occurence.f_object_id==long(request.args[0]))
    grid = SQLFORM.grid(...)
    return dict(upload_form=upload_form, grid=grid)

检查回调函数:

def analyse_occurence_data(form):
    import types
    if isinstance(form.vars.f_temp_file, types.StringType):
        filename = None
    else:
        filename = form.vars.f_temp_file.filename
    occurence = form.vars.f_refid
    object_id = form.vars.f_object_id
    obj = db.t_object(object_id)
    # several checks and complementary form.vars.field = value
    potential_entry = db((db.t_object_occurence.f_refid==occurence)&(db.t_object_occurence.f_object_id==object_id)).select().first()
    if potential_entry is None:
        # let's insert a new record!
        return
    elif (filename is None) or (potential_entry.f_temp_file is not None):
        form.errors.f_temp_file = "The occurence "+occurence+" of "+obj.f_refid+" already exists in repository."
    elif potential_entry is not None:
            # THIS IS WHERE I'd like to decide to update instead of insert!

由于我的应用程序在调用其回调之前无法知道它是否必须插入或更新记录,因此我正在寻找正确的指令,以便我的 SQLFORM 能够做正确的事情。

非常感谢。

【问题讨论】:

  • 为什么不只是制作一个常规方法的输入表单和更新表单...您似乎已经有了要使用补充信息更新的记录的 ID(附加文件) ?
  • 感谢您的建议。但我认为这行不通:第一,我需要一个单一的表单来保持用户的生活简单,他们的大脑已经忙于更复杂的任务,他们不会接受一个至少不像 (很旧)一个他们已经有(你不知道)。第二,在我调用回调之前我没有 ID。 JQuery 可以调用一些 ajax 并将插入表单更改为更新表单...有趣但第三,总而言之,对我来说编码和维护会更加复杂,我很确定我们可以按照我的方式来做思考。 :)
  • 是的,我们可以,我只是在问你为什么要走这条路……让我仔细阅读代码,然后回复你……
  • 不相关,但语法更好 Field('f_object_id', db.t_object, label=T('Object')), -> Field('f_object_id', 'reference t_object', label=T ('对象')),
  • 困难的地方是如何确保您将在没有 id 的情况下更新正确记录...您需要有一组可以作为复合主键引用的字段和这些字段中的值应该使它们唯一,并考虑主键或记录的代理 id 的反射......

标签: python web2py


【解决方案1】:

这是一个可以帮助您调整上述代码的工作示例:

def onvalidation_insert_or_update(form):
    row = db(db.mytable.f1 == form.vars.f1).select(db.mytable.ALL).first()
    if row is not None:
        id = row.id
        db(db.mytable.id == id).update(f2=form.vars.f2)
        session.flash = 'Record updated'
    else:
        id = db.mytable.insert(**form.vars)
        session.flash = 'Record inserted'
    db.commit()
    session.flash = 'Record inserted'
    redirect(URL(c='default', f='read_form', args=id))
    return


def basic_controller():
    form = SQLFORM(db.mytable)
    if form.process(dbio=False, onvalidation=onvalidation_insert_or_update).accepted:
        pass
    elif form.errors:
        response.flash = 'form has errors'
    else:
        response.flash = 'please fill the form'
    grid = SQLFORM.grid(db.mytable)
    return dict(form=form, grid=grid)

def read_form():
    form = SQLFORM(db.mytable, record=request.args(0), readonly=True)  # readonly=True make form not modifiable
    return dict(form=form)

我无法附加工作应用程序...但也许,如果您向 web2py 用户 google 组提出您的问题,我可以将其与电子邮件一起附加,这对于此类问题来说更方便。

【讨论】:

  • 嗨,理查德,感谢您抽出宝贵时间。我很难实施您的建议,因为我必须改进我的复杂处理。即使您的解决方案应该“按原样”工作,它似乎在我的环境中有副作用,因此我无法使其正常工作。正如你所建议的,我将把这一点发展到 web2py 用户组中。
  • 好,见,这样会更容易,因为你的问题类型很难遵循问答结构...... :)
猜你喜欢
  • 1970-01-01
  • 2015-12-18
  • 1970-01-01
  • 1970-01-01
  • 2012-03-06
  • 2020-07-02
  • 1970-01-01
  • 2018-02-25
  • 1970-01-01
相关资源
最近更新 更多