@Atroshchenko-Dima
Python, postgres

Как добавить возможность скачивания выгрузки из БД на сайт?

как добавить возможность скачивания таблицы(выгрузка из БД sql запросом) в формате xlsx на сайт.
Пользователь должен выбрать даты выгрузки и нажать кнопку скачать. Попробовал реализовать таким способом, но не получается добиться рабочего состояния кода.

Фрагмент файла app.py
# соединение с БД
conn = psycopg2.connect(**params)


@app.route("/", methods=["GET","POST"])
def index():
    form_visible = True
    cur = conn.cursor()
    if request.method == "POST":
        # Получаем промежуток дат из формы
        start_date = request.form["start_date"]
        end_date = request.form["end_date"]
        # Форматируем даты в соответсвии с форматом в базе данных
        start_date = datetime.strptime(start_date,"%Y-%m-%d")
        end_date = datetime.strptime(end_date,"%Y-%m-%d")
        # Запрос к БД с использованием параметров дат
        cur = conn.cursor()
        cur.execute("SELECT * FROM toplivo WHERE date BETWEEN %s AND %s ORDER BY date ASC;",(start_date,end_date)) 
        rows = cur.fetchall()
        cur.close
        # Отоброжение полученных данных на странице
        return render_template("index.html", rows=rows, form_visible=True)
    else:
        cur.execute("SELECT * FROM toplivo;")
        rows = cur.fetchall()
        cur.close() 
        return render_template("index.html",rows=rows, form_visible=form_visible)


@app.route("/download", methods=["POST"])
def download():
    # Получаем начальную и конечную даты из скрытых полей на поле
        start_date = request.form["start_date"]
        end_date = request.form["end_date"]
        # Форматируем даты в соответсвии с форматом в базе данных
        start_date = datetime.strptime(start_date,"%Y-%m-%d")
        end_date = datetime.strptime(end_date,"%Y-%m-%d")
        # Запрос к БД с использованием параметров дат
        cur = conn.cursor()
        cur.execute("SELECT * FROM toplivo WHERE date BETWEEN %s AND %s ORDER BY date ASC;",(start_date,end_date)) 
        rows = cur.fetchall()
        cur.close
        # Сохраняем таблицу в формате xlsx и отправляем для скачивания на клиент
        output = BytesIO()
        workbook = xlsxwriter.Workbook(output)
        worksheet = workbook.add_worksheet()
        # Записываем данные в xlsx
        header_row = ["Месяц", "Контрагент","Вид обязательств", "Договор", "Номер счет фактуры", "Дата", "Станция", "k", "Количество, тыс.тут.куб.м", "Стоимость без НДС, руб.", "Цена руб./тыс.м3", "Калорийность поставщика", "Калорийность электростанции", "Количество, тут","Цена руб./тут", "Для средневзвеса калорийности поставщика", "Для средневзвеса калорийности станции", "Скачать договор"]
        for j, header in enumerate(header_row):
             worksheet.write(0,j, header)
        for i, row in enumerate(rows):
             for j, value in enumerate(row):
                  if isinstance(value, datetime.date):
                       value = value.strftime('%Y-%m-%d')
                  worksheet.write(i + 1, j, value)
        workbook.close()              
        output.seek(0)
        xlsx_data = output.read()

        #Отправлвяем файл на скачивание
        response = flask.make_response(xlsx_data)
        response.headers['Content-Type'] = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
        response.headers['Content-disposition'] = 'attachment; filename = toplivo.xlsx'
        return response


if __name__ == "__main__":
    app.run()


Фрагмент файла index.html
{% if form_visible %}
    <form method ="post" action="/">
    <label for="start_date  ">Дата с:</label>
    <input type="date" id ="start_date"name ="start_date"><br><br>

    <label for="end_date">Дата по:</label>
    <input type="date" id ="end_date"name ="end_date"><br><br>

    <input type = "submit" value="Применить">
    </form>
{% endif %}
<body>

.......
.......
......

        <tbody class="table-hover">
{% for row in rows %}
            <tr>
                <td align="center">{{ row[0] or ''  }}</td>
                <td align="center">{{ row[1] or ''  }}</td>
                <td align="center">{{ row[2] or ''  }}</td>
                <td align="center">{{ row[3] or ''  }}</td>
                <td align="center">{{ row[4] or ''  }}</td>
                <td align="center">{{ row[5].strftime('%Y-%m-%d') or ''  }}</td>
                <td align="center">{{ row[6] or ''  }}</td>
                <td align="center">{{ row[7] or ''  }}</td>
                <td align="center">{{ row[8] or ''  }}</td>
                <td align="center">{{ row[9] or ''  }}</td>
                <td align="center">{{ row[10] or ''  }}</td>
                <td align="center">{{ row[11] or ''  }}</td>
                <td align="center">{{ row[12] or ''  }}</td>
                <td align="center">{{ row[13] or ''  }}</td>
                <td align="center">{{ row[14] or ''  }}</td>
                <td align="center">{{ row[15] or ''  }}</td>
                <td align="center">{{ row[16] or ''  }}</td>
                <td align="center"><br><button>скачать</button></td>
            </tr>
{% endfor %}
        </tbody>
    </table>
{% if not form_visible %}
<form method="post" action="/download">
<input type="submit" value="Скачать">
</form>
{% endif %}

{% if form_visible %}
    <br><br>
{% endif %}
{% if form_visible %}
    <form method ="post" action="/"></form>
    <label for="start_date">Начальная дата:</label>
    <input type="date" id ="start_date"name ="start_date"><br><br>

    <label for="end_date">Конечная дата:</label>
    <input type="date" id ="end_date"name ="end_date"><br><br>

    <input type = "submit" value="Обновить">
   </form>
{% endif %}
</body>
</html>
  • Вопрос задан
  • 100 просмотров
Пригласить эксперта
Ответы на вопрос 1
Stalker_RED
@Stalker_RED
Если устроит csv вмето xlsx, то достаточно select ... into outfile 'filename.csv'
И отдать потом файл.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы
от 100 000 до 200 000 ₽
CTRL+ Москва
от 250 000 до 320 000 ₽
CTRL+ Москва
от 200 000 до 300 000 ₽
22 нояб. 2024, в 00:55
500 руб./за проект
21 нояб. 2024, в 23:30
300000 руб./за проект
21 нояб. 2024, в 22:21
3000 руб./в час