@Atroshchenko-Dima
Python, postgres

Как правильно передать массив данных на сервер и в ссылку для скачивания?

Мне нужно реализовать возможность скачивания выгрузки из базы данных в формате xlsx.

Пользователь может выбрать какие столбцы нужно выгрузить(переменная columns) и использовать фильтр по нескольким столбцам - переменные: year, station, indicators.

Сейчас при нажатии кнопки скачать происходит скачивание пустой таблицы в excel, с прописанными в worksheet.append заголовками. Подскажите, пожалуйста, что не так? Я так понимаю нужно как-то переписать код, чтоб заголовки не сразу задавались в явном виде, а брались исходя из выбора пользователя. В остальном даже нет идей, что может быть не так.

в html файле прикладываю как обрабатываются таблица и заголовки + саму ссылку, в остальном используется классический select multiple.
index.html

<tbody class="table-hover">

<table class="table-fill">
  <thead>
    <tr>
      {% for column in columns %}
      <th>{{ column }}</th>
      {% endfor %}
    </tr>
  </thead>

{% for row in rows %}
    <tr>
      {% for column in columns %}
      <td>{{ row[loop.index0] }}</td>
      {% endfor %}
    </tr>
{% endfor %}
    </tbody>
  </table>
</body>


<a href = "{{url_for('download', columns = request.args.getlist('columns'), year = request.args.getlist('year'), indicators=request.args.getlist('indicators'), station=request.args.getlist('station'))}}">Скачать</a>


app.py

@app.route("/download", methods=["GET","POST"])
def download():
    if request.method == "GET":
        # Получение переменных выбранных пользователем и обработка массива для select multiple
        year = request.form.getlist("year")
        year = [int(i) for i in request.form.getlist("year") if i.isdigit()]
        station = request.form.getlist("station")
        station = [str(i) for i in request.form.getlist("station")]
        indicators = request.form.getlist("indicators")
        indicators = [str(i) for i in request.form.getlist("indicators")]
        columns = request.form.getlist("columns")
        columns = [str(i) for i in request.form.getlist("columns")]
        # Запрос к БД с использованием параметров переменных
        cur = conn.cursor()
        cur.execute("SELECT {} FROM fact_indicators WHERE fact_year = ANY(%s) AND fact_indicators = ANY(%s) AND fact_station_name = ANY(%s);"
                    .format(",".join(["\"{}\"".format(c) for c in columns])),(year, indicators, station))
        rows = cur.fetchall()
        cur.close
        # Имя скачавшегося файла
        filename = "fact_T2.xlsx"
        # Путь файла(выбран стандартный, downloads)
        filepath = os.path.join(os.path.dirname(__file__), filename)
        # создаем новую книгу excel
        workbook = openpyxl.Workbook()
        # Получаем активный лист
        worksheet = workbook.active
        # Заполняем таблицу данными из запроса к базе данных
        worksheet.append(["Год", "Станция","Показатели", "Е/И", "Январь", "Февраль", "Март", "1 кв", "Апрель", "Май", "Июнь", "2 кв", "Июль", "Август","Сентябрь", "3 кв", "Октябрь", "Ноябрь","Декабрь","4 кв","Год"])
        for row in rows:
            worksheet.append(list(row))           
        # Сохраняем результат в файл
        workbook.save(filepath)
        # Возвращаем файл на скачивание в папку downloads
        return send_from_directory(os.path.dirname(__file__),  path=filename, as_attachment=True)
    else:
        return redirect(url_for("index"))


Рабочий код для выгрузки БД на сайт с обработкой показателей выбранных пользователем

@app.route("/", methods=["GET","POST"])
def index():
    cur = conn.cursor()
    cur.execute("SELECT * FROM fact_indicators;") 
    rows = cur.fetchall()
    cur.close
    
    if request.method == "POST":
        # Получение переменных выбранных пользователем и обработка массива для select multiple
        year = request.form.getlist("year")
        year = [int(i) for i in request.form.getlist("year") if i.isdigit()]
        print(year)
        station = request.form.getlist("station")
        station = [str(i) for i in request.form.getlist("station")]
        print(station)
        indicators = request.form.getlist("indicators")
        indicators = [str(i) for i in request.form.getlist("indicators")]
        print(indicators)
        columns = request.form.getlist("columns")
        columns = [str(i) for i in request.form.getlist("columns")]
        print(indicators)
        # Запрос к БД с использованием переменных
        cur = conn.cursor()
        cur.execute("SELECT {} FROM fact_indicators WHERE fact_year = ANY(%s) AND fact_indicators = ANY(%s) AND fact_station_name = ANY(%s);"
                    .format(",".join(["\"{}\"".format(c) for c in columns])),(year, indicators, station))
        rows = cur.fetchall()
        cur.close
        # Отоброжение полученных данных на странице
        return render_template("index.html", rows=rows, columns=columns, form_visible=True)
    else:
        return render_template("index.html", rows=rows, form_visible=False)
  • Вопрос задан
  • 67 просмотров
Решения вопроса 1
Mi11er
@Mi11er
A human...
Конечно ... без понимания что у вас на беке, тяжко ... Могу вам дать кусок кода для django проекта.
Дальше только ваша фантазия что с этим делать.

Судя по вашей задаче, так как вы передаете колонки для выбора, то их надо передать в select для sql\orm , дальше уже формировать xls и отдать в response
j = json.dumps(result, ensure_ascii=False, default=str)
df = pd.read_json(j)
with BytesIO() as b:
     writer = pd.ExcelWriter(b, engine='xlsxwriter')
     df.to_excel(writer, sheet_name='Sheet1')
     writer.save()
     filename = f"{bp.title}.xlsx"
     content_type = 'application/vnd.ms-excel'
     response = HttpResponse(b.getvalue(), content_type=content_type)
     response['Content-Disposition'] = 'attachment; filename="' + filename
     return response
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы