Как загрузить документ, созданный с помощью python -docx в проекте Django? - PullRequest
0 голосов
/ 14 января 2020

Я пытаюсь понять, как загрузить текстовый документ, созданный с помощью python -docx, в мое приложение django (я все еще учусь, и впервые работаю с документами); с помощью ajax я отправляю всю информацию, необходимую для просмотра, и вызываю функцию, которая использует эту информацию и возвращает документ, затем я пытаюсь отправить этот документ в качестве ответа, чтобы загрузить его с помощью Кнопка «Загрузить» (или показать диалог загрузки веб-браузера) в том же шаблоне, откуда я отправляю данные, но вот где я застрял.

, чтобы отправить этот документ в качестве ответа для загрузки это с помощью кнопки «Загрузить» (или показать диалог загрузки веб-браузера) в том же шаблоне, откуда я отправляю данные, но вот где я застрял.

Что у меня есть до сейчас:

1) В javascript отправляю информацию следующим образом:

data = {
        categoria: cat,
        familia: fam,
        Gcas: gcas,
        FI: FI,
        FF: FF,
        Test: test,
        Grafica: grafica
    },
        $.ajax({
            type: 'post',
            headers: {
                "X-CSRFToken": csrftoken
            },
            url: url,
            data: { json_data: JSON.stringify(data) },

            success: function (response) {
                $('#instrucciones').hide(); //Hide a div with a message 
                $('#btndesc').show(); //Show the button to download the file generated                
            }
        });
    return false;
}

2) В моем Django виде:

def Documento(request):
    if request.method == "GET":
        context={}
        context['form'] = catForm
        return render(request, 'report/report_base.html', context)

    if request.method == 'POST':
    #Data from ajax
    datos = request.POST.get('json_data')
    jsondata = json.loads(datos)
    Gcas = jsondata['Gcas']
    FI = jsondata['FI']
    FF = jsondata['FF']
    grafica = jsondata['Grafica']
    #Using function to create the report
    Reporte = ReporteWord(Gcas, FI, FF, grafica)
    #Response
    response = HttpResponse(content_type='application/vnd.openxmlformats-
    officedocument.wordprocessingml.document')
    response['Content-Disposition'] = 'attachment; filename = "Reporte.docx"'
    response['Content-Encoding'] = 'UTF-8'
    Reporte.save(response)
    return response

3) Моя функция для создания документа выглядит так:

def ReporteWord( gcas, FI, FF, Chart):
    #Cargamos el template
    template = finders.find('otros/Template_reporte.docx')
    document = Document(template) 

    #Header
    logo = finders.find('otros/logo.png')
    header = document.sections[0].header
    paragraph = header.paragraphs[0]
    r = paragraph.add_run()
    r.add_picture(logo)

    #Adding title
    titulo = document.add_heading('', 0)
    titulo.add_run('Mi reporte').bold = True
    titulo.style.font.size=Pt(13)
    .
    Many other steps to add more content    
    .
    .
    #IF I SAVE THE FILE NORMALLY ALL WORKS FINE
    #document.save(r'C:\tests\new_demo.docx')

    return document

Я буду очень благодарен за любую идею или предложение, большое спасибо заранее.

ПРИМЕЧАНИЕ: я рассмотрел эти ответы (и другие) без везения.

Q1 , Q2 , Q3 , Q4

ОБНОВЛЕНИЕ : Благодаря полученной обратной связи я наконец-то нашел, как сгенерировать документ и показать диалог загрузки:

Как было предложено, лучший способ добейтесь его использования с использованием представления, а не ajax, поэтому окончательные обновления в коде:

a) Обновление представления для работы, как показано в обратной связи

b) JavaScript - Ajax элемент управления для метода POST был удален, и теперь все обрабатывается непосредственно с помощью python (дополнительный код не требуется)

1) Просмотр:

def Reporte(request):
    if request.method == "GET":
        context={}
        context['form'] = catForm
        return render(request, 'reportes/reporte_base.html', context)

    if request.method == 'POST':
        #Getting data needed after submit the form in the page
        GcasID = request.POST.get('GCASS')
        FI = request.POST.get('dp1')
        FF = request.POST.get('dp2')
        Grafica = request.POST.get('options')

        #Function to obtain complete code from GcasID 
        Gcas =  GcasNumber(GcasID)

        #Report creation
        Reporte = ReporteWord(Gcas, FI, FF, Grafica)

        #PART UPDATED TO SHOW DOWNLOAD REPORT DIALOG
        bio = io.BytesIO()
        Reporte.save(bio)  # save to memory stream
        bio.seek(0)  # rewind the stream
        response = HttpResponse(
        bio.getvalue(),  # use the stream's contents
        content_type="application/vnd.openxmlformats-officedocument.wordprocessingml.document",
    )

        response["Content-Disposition"] = 'attachment; filename = "Reporte.docx"'
        response["Content-Encoding"] = "UTF-8"
        return response

С этими изменениями теперь, когда я нажимаю " Создать отчет »(кнопка отправки формы) все работает как положено (плюс не нужно больше библиотек). В конце, как вы и предложили, сделать это проще, чем использовать ajax.

Большое спасибо всем за любезную помощь.

1 Ответ

0 голосов
/ 15 января 2020

Python -docx метод Document.save() принимает поток вместо имени файла. Таким образом, вы можете инициализировать объект io.BytesIO() для сохранения документа, а затем отправить его пользователю.

Reporte = ReporteWord(Gcas, FI, FF, grafica)
bio = io.BytesIO()
Reporte.save(bio)  # save to memory stream
bio.seek(0)  # rewind the stream
response = HttpResponse(
    bio.getvalue(),  # use the stream's contents
    content_type="application/vnd.openxmlformats-officedocument.wordprocessingml.document",
)
response["Content-Disposition"] = 'attachment; filename = "Reporte.docx"'
response["Content-Encoding"] = "UTF-8"
return response

Это будет работать, если вы используете обычную ссылку или форму для отправки запроса, но поскольку вы используете $.ajax, вам может потребоваться выполнить дополнительную работу на стороне браузера, чтобы клиент загрузил файл. Было бы проще не использовать $.ajax.

...