Django-在模板中调用函数并将该函数的值返回到同一页面时出现问题

Django-在模板中调用函数并将该函数的值返回到同一页面时出现问题,django,python-3.x,django-templates,django-views,django-request,Django,Python 3.x,Django Templates,Django Views,Django Request,我有一个页面,用于呈现数据库中的对象列表。我需要按下一个按钮来查询我的数据库中的特定对象,在我的视图中执行一些操作,并返回一个价格值,我希望该价格值显示在同一页面上的弹出气泡中,而无需重新加载它,以代替我的填充文本。我试着创建一个表单,表单中的按钮在值字段中有对象的id,并将该值发送到原始页面的视图,然后调用一个函数来处理我想用该id做的事情。我请求对象的id,将其传递给新的视图函数,并查询我的数据库并尝试返回值。我在原始页面的视图t中发布一个if request.POST语句,并将呈现的变量更

我有一个页面,用于呈现数据库中的对象列表。我需要按下一个按钮来查询我的数据库中的特定对象,在我的视图中执行一些操作,并返回一个价格值,我希望该价格值显示在同一页面上的弹出气泡中,而无需重新加载它,以代替我的填充文本。我试着创建一个表单,表单中的按钮在值字段中有对象的
id
,并将该值发送到原始页面的视图,然后调用一个函数来处理我想用该id做的事情。我请求对象的
id
,将其传递给新的视图函数,并查询我的数据库并尝试返回值。我在原始页面的视图t中发布一个
if request.POST
语句,并将呈现的变量更改为我想要显示的新值。当我按下按钮时,我在弹出框中得到相同的填充文本,在控制台中我得到以下错误:

ValueError: The view engine.views.search_list didn't return an HttpResponse object. It returned None instead.
因此,无论何时调用视图函数,似乎都必须返回HTTP请求。我已经尝试在我的新视图函数中返回一个呈现的响应,并在检查
if request.POST之后,将新值作为上下文传递:

return render(request, 'original_page.html', {'value':new_value})
我也犯了同样的错误。如何在同一页上返回所需的值而不出现此错误?我尝试过使用带有空值的
HttpResponse
,以及
redirect('some_place.html')
,但都没有成功。我有一个Iframe,它可以阻止我的html页面重新加载。以下是我正在使用的代码:

HTML

视图-原始渲染视图


您试图做的事情通常应该通过异步调用(AJAX)来处理。按照当前的设置方式,表单将被提交,页面将重新加载。这不是一种用户友好的体验,而且是“Web1.0”的做事方式(还有,
iframes
…糟糕!)。以下是我如何更改您的设置:

新视图

def ajax_get_price(request):
    response = {}
    product_id = request.POST.get('productId')

    try:
        item = Product.objects.get(id=product_id)
        response['price'] = item.price
        response['success'] = True
    except ObjectDoesNotExist:
        response['error'] = "Item not found!"
        response['success'] = False

    return JSONResponse(response)
新前端处理器

您可以通过JavaScript中的AJAX调用将数据发送到这个新的“视图”。这里我将以jQuery为例:

$("button[name='productId']").on("click", function() {
    var productID = $(this).val();
    $.ajax({
        'data': {
            'productId': productID
        },
        'type': "POST",
        'url': "{% url 'myproject:ajax_get_price' %}"
    })
    .done(function(json) {
        if(json.success == true) {
            var itemPrice = json.price;
            // TODO: Do something with the price here (show a popup, tooltip, whatever)
        } else {
            if(json.hasOwnProperty('error') {
                // TODO: Show the error
            })
        }
    })
    .fail(function(xhr, status, error) {
        // TODO: Handle this error case also
    });
});
除了此存根之外,您还需要处理一些事情:

  • 在JavaScript代码中调用
    $.ajax()
    之前,您可能需要在
    中处理CSRF(跨站点请求伪造)令牌
  • 您可能应该检查视图中的虚假查询(请求是否为GET调用?)和其他类似的边缘情况

我不清楚你是如何填充泡沫的。通常您会使用JavaScript来实现这一点。另外,错误消息让您感到困惑的是什么?视图需要返回HttpResponse对象;那么你试过退回一个包含你的价格的吗?@DanielRoseman我编辑了我的代码,以显示我是如何在html代码中创建弹出气泡的。我想我尝试将新值呈现为上下文,如:
returnrender(请求,'search\u result\u list.html',{'price':price})
。是否有其他方法可以将值作为http响应返回并使用它?这实际上不需要是post,因为它不会更改数据库中的数据,这将避免csrf问题。
def search_list(request):
results = Product.objects.all().order_by('name')
price = 'no_price'
if request.POST:
    print(request.POST.get('productId'))
    tcg_price = get_price(request)
    return render(request, 'search_result_list.html', {'tcg_price': tcg_price})
else: ...
return render(request, 'search_result_list.html', {'price': price, 'results':results})
def ajax_get_price(request):
    response = {}
    product_id = request.POST.get('productId')

    try:
        item = Product.objects.get(id=product_id)
        response['price'] = item.price
        response['success'] = True
    except ObjectDoesNotExist:
        response['error'] = "Item not found!"
        response['success'] = False

    return JSONResponse(response)
$("button[name='productId']").on("click", function() {
    var productID = $(this).val();
    $.ajax({
        'data': {
            'productId': productID
        },
        'type': "POST",
        'url': "{% url 'myproject:ajax_get_price' %}"
    })
    .done(function(json) {
        if(json.success == true) {
            var itemPrice = json.price;
            // TODO: Do something with the price here (show a popup, tooltip, whatever)
        } else {
            if(json.hasOwnProperty('error') {
                // TODO: Show the error
            })
        }
    })
    .fail(function(xhr, status, error) {
        // TODO: Handle this error case also
    });
});