Django - проблема вызова функции в шаблонах и возвращения рендеринга значения этой функции на той же странице
У меня есть страница, которая отображает список объектов из моей базы данных. Мне нужно нажать кнопку, которая запрашивает в моей базе данных конкретный объект, выполняет какие-то действия в моих представлениях и возвращает значение цены, которое я хотел бы отобразить на этой же странице во всплывающем окне, без перезагрузки, вместо Текст наполнителя у меня есть. Я попытался сделать это, создав форму с кнопкой, которая имеет объект id
в поле значения и отправив это значение в представление моей исходной страницы, а затем я вызываю функцию, которая обрабатывает то, что я хочу сделать с этим идентификатором. Я запрашиваю объект id
, передайте его новой функции просмотра, запросите мою базу данных и попробуйте вернуть значение. Я делаю if request.POST
утверждение в представлении исходной страницы t, и измените отображаемую переменную на новое значение, которое я хочу отобразить. Когда я нажимаю кнопку, я получаю тот же текст заполнителя во всплывающем окне и в консоли получаю следующую ошибку:
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
<iframe name="submit-frame" style="display: none"></iframe>
<form action="{% url 'search_list' %}" method="post" target="submit-frame">{% csrf_token %}
<button name="productId" value="{{product.id}}" data-toggle="popover" data-animation="true" data-content="{{price}}" type="" id='button'>Reveal Price</button>
</form>
<script type="text/javascript">
$('[data-toggle="popover"]').popover({
container: 'body',
delay: { "show": 100, "fade": 100 },
})
</script>
Views - функция для получения нового значения
def get_price(request):
product_id = request.POST.get('productId')
item = get_object_or_404(Product, id=product_id)
price = item.price
return price
Представления - Оригинальное Представление Представления
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})
1 ответ
То, что вы пытаетесь сделать, обычно обрабатывается с помощью асинхронного вызова (AJAX). То, как вы сейчас настраиваете, форма отправляется, и страница перезагрузится. Это не удобный для пользователя способ, а "Web 1.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)
Новый интерфейсный обработчик
Вы бы отправляли данные в это новое "представление" через вызов AJAX в JavaScript. Я буду использовать 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
});
});
Есть несколько вещей, с которыми вам нужно справиться, помимо этой заглушки:
- Скорее всего, вам придется обрабатывать токен CSRF (подделка межсайтовых запросов) в
beforeSend
позвонить$.ajax()
в вашем коде JavaScript. - Вероятно, вам следует проверить поддельные запросы в вашем представлении (это запрос GET?) И другие подобные крайние случаи.