Как изменить GET-запрос, чтобы вызвать ответ с вложением файла (законным образом)?
У меня есть проект Django, который использует шахматный модуль python для отображения шахматной доски в главном представлении. По умолчанию это пустая доска:
views.py
import chess, chess.pgn
def index(request, pgn_slug=None):
board = chess.Board()
game = chess.pgn.Game.from_board(board)
game.headers["DrawOffered"] = "False"
Главная индексная функция перехватывает AJAX-запросы и обслуживает ответы:
from django.http import JsonResponse
if request.headers.get('x-requested-with') == 'XMLHttpRequest':
...
return JsonResponse(response_obj)
Или он отобразит страницу:
from django.http import HttpResponse
else:
html = get_html(game, board)
return HttpResponse(html)
Я хочу, чтобы один elif возвращал вложение .txt, основанное на функциях написания игры python-chess . Как мне добиться этого с хорошо сформированными запросами и ответами? Django, кажется, имеет выделенный объект ответа для такого рода вещей, но я не могу сложить два и два вместе. Возможно, что-то вроде этого?:
from django.http import FileResponse
elif request._____ == 'download': # what could mark the request?
file_name = 'foo.txt'
file = open(filename, 'wt')
file.write(str(game))
return FileResponse(file, as_attachment=True,
filename=file_name)
Запрос запускается кнопкой на той же странице и функцией JavaScript и вызывает либо URL окна, либо URL, который динамически передается функции из AJAX:
<script>
function downloadPGN(URL) {
if (URL === undefined) {
URL = window.location.href
}
// ... GET request with modified headers?
</script>
<button type="button" id="downloadButton"
onClick="downloadPGN()">↓</button>
Я понимаю, что мой вопрос похож на несколько других, но все решения казались десятилетней давности и очень запутанными для того, что кажется мне довольно простой проблемой. Мне кажется, что я упускаю какую-то маленькую, жизненно важную деталь. Кто-нибудь может помочь?
Я обнаружил, что использование атрибута html download создает различные GET-заголовки. Не уверен в переносимости, но это помогло отделить запросы GET от GET с загрузкой на моей локальной системе.
fetch = request.headers.get('Sec-Fetch-Site')
dest = request.headers.get('Sec-Fetch-Dest')
if fetch == 'same-origin' and dest == 'empty':
disp = 'attachment; filename="foo.txt"'
return HttpResponse(get_download(game), headers={
'Content-Disposition': disp })
else:
html = get_html(request.path, game, board)
return HttpResponse(html)