HX-триггер для выдачи запроса с использованием аргументов
Я хочу создать запрос после триггера с использованием htmx после нажатия на кнопку с помощью django:
def SomeView(request, var1, var2):
trigger_data = json.dumps({"dlstart": {"pid": pid, "var1": var1}})
return HttpResponse("", headers={"HX-Trigger": trigger_data})
На вкладке Network я вижу, что GET-запрос работает. Но теперь я хочу добавить два аргумента из trigger_data
к моему hx-get
динамически. В htmx я не нашел способа добиться этого, поэтому я сделал обходной путь на JS (от которого я с радостью откажусь в пользу решения только для htmx):
document.body.addEventListener("dlstart", function() {
const url = `/someURL/${event.detail.pid}/${event.detail.var1}`;
const filename = "test.png";
fetch(url)
.then(response => {
if (!response.ok) {
throw new Error('was not ok');
}
return response.blob();
})
.then(blob => {
const link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = filename;
document.body.appendChild(link);
link.click(); // feels so ugly
document.body.removeChild(link);
})
});
Я полагаю, что какая-то комбинация из hx-get
и динамического добавления аргументов тоже должна работать?
Скачать файл, сгенерированный сервером, с помощью htmx-запросов - довольно подло. Но есть простой обходной путь, который позволяет обойтись вообще без пользовательского JavaScript.
Общая идея заключается в том, чтобы иметь представление, которое предлагает клиенту только вариант загрузки, как это делаете вы. Тогда хитрость заключается в том, чтобы просто перенаправить запрос на это представление.
В вашем случае сначала рефакторим SomeView
:
from django.urls import reverse_lazy
def SomeView(request, var1, var2):
dl_url = reverse_lazy("some-url", kwargs=dict(pid=pid, var1=var1))
return HttpResponse(headers={"Hx-Redirect" : dl_url})
Это приведет к перенаправлению клиента на указанный url. Затем в DLView
возвращает FileResponse
, что позволяет легко предложить клиенту возможность загрузки:
from django.http import FileResponse
def DLView(request, pid, var1):
# do stuff
pdf = pdf_create(prod, var1)
return FileResponse(open(pdf, "rb"), as_attachment=True, filename="test.pdf")
Это представление должно делать то, что делает ваш JavaScript, открывая диалог загрузки в браузере. Надеюсь, это то, чего вы хотите добиться.
Нота:
В соответствии с соглашением, имена функций в Python должны быть в snake_case
, а имена классов - в PascalCase
. Таким образом, вместо def DLView...
должно быть def dl_view...
.