使用类似查询时的TypeError

时间:2015-07-06 11:41:14

标签: python postgresql flask sqlalchemy

我在PostgreSQL数据库上使用Flask / SQLAlchemy处理Python应用程序。尝试实现Flask / jQuery自动填充搜索表单,如Flask AJAX Autocomplete

所述

在我的_base模板中,我有:

<script type=text/javascript>
    $SCRIPT_ROOT = {{ request.script_root|tojson|safe }};
</script>

<script type="text/javascript">
    $(function() {
        $( "#searchfood" ).autocomplete({

            source: function( request, response ) {
                    $.getJSON($SCRIPT_ROOT + "/_search_food", {
                        search: request
                    }, function( data ) {
                        response( $.map( data.results, function( item ) {
                            return {
                                label: item.name,
                                value: item.id
                            }
                        }));
                    });
            }
        });
    });
</script>

在app.py中:

@app.route('/_search_food')
def search_food():
    search = request.args.get('search')
    results = Foods.query.filter(Foods.name.like('%' + search + '%')).all()
    return jsonify(results)

Ajax调用似乎有效,因为控制台会向search_food显示触发器,但是如果我直接浏览页面http://localhost:5000/_search_food?search%5Bterm%5D=Mar并出现500错误:TypeError: cannot concatenate 'str' and 'NoneType' objects。由结果查询触发:

results = Foods.query.filter(Foods.name.like('%' + search + '%')).all()

它是否从数据库中获取结果?或者我必须将输入转换为其他格式? Foods模型中的name对象是一个字符串。

1 个答案:

答案 0 :(得分:2)

searchNone,因为您的GET请求中没有此类参数,因此request.args.get('search')返回了默认值。

相反,您的参数称为search[term],因为jQuery传递了一个具有term属性的对象。提取它:

$.getJSON($SCRIPT_ROOT + "/_search_food", {
    search: request.term
},

否则jQuery会尝试使用PHP约定来序列化对象。

另见jQueryUI autocomplete documentation

  

[...] 回调有两个参数:

     
      
  • 具有单个term属性的请求对象,该属性引用文本输入中当前的值。
  •   
     

[...]

请注意,您不能只将Food()个对象转换为JSON。选择要在自动填充小部件中显示的属性;它需要一个字符串数组或一个具有labelvalue属性的对象数组。

您可以使用列表推导来生成:

results = Foods.query.filter(Foods.name.like('%' + search + '%')).all()
return jsonify(results=[{'label': f.name, 'value': f.id} for f in results])

使用名称作为自动完成值。请注意,出于安全原因,jsonify()始终生成JSON对象,因此您需要在JavaScript端提取数组:

$.getJSON($SCRIPT_ROOT + "/_search_food", {
    search: request
}, function( data ) { response(data.results); });