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....

Вернуться на верх