Flask - Многопользовательский доступ с OOP - PullRequest
0 голосов
/ 28 января 2020

Я создал приложение с flask, но у меня проблема с многопользовательским доступом bcs глобальных переменных . Всякий раз, когда я запускаю сценарий (это может занять несколько минут), и кто-то другой пытается получить доступ к странице и запустить сценарий, там также появляется коллизия, и данные обоих пользователей смешиваются.

Я действительно понимаю, что я должен использовать OOP в этом случае, но я не могу повторить использование OOP для этого приложения (да, я начинающий OOP). Может кто-нибудь дать мне подсказку или немного кода о OOP для этого случая?

Очень ценится.

Python:

from flask import Flask, render_template, url_for, request, redirect, Response
from datetime import datetime
import time
import pandas as pd
import re
import os


app = Flask(__name__)


@app.route('/', methods=['POST', 'GET'])
def index():

    if request.method == 'POST':
        start_date = request.form["Start_date"]
        end_date = request.form["End_date"]
        dates = pd.period_range(start=start_date, end=end_date, freq='D')
        global s_date
        global f_date
        s_date = dates[0]
        f_date = dates[-1]
        print(s_date, f_date)
        query = request.form["query"].strip()
        splitted = query.split("\r\n")

        global fiii
        fiii = pd.DataFrame()

        for x in splitted:
            print(x)
            for date in dates:
                print(date)

                directory = '/home/USER/Parquets/{}/{:02d}/{:02d}/'.format(date.year, date.month, date.day)
                for filename in os.listdir(directory):
                    if filename.endswith(".parquet"):
                        df = pd.read_parquet(directory)
                        df.set_index("query", inplace=True)


                        if request.form.get('lowercase') == "on":
                            df.index = df.index.str.casefold()
                        if request.form.get('sensitive') == "on":

                            fiii = fiii.append(df.filter(regex=re.compile(x), axis=0))
                        else:

                            fiii = fiii.append(df.filter(regex=re.compile(x, re.IGNORECASE), axis=0))

        fiii = fiii.groupby(['query'])["total"].sum().sort_values(ascending=False)

        if request.form.get('csv') == "on":
            return redirect("/getCSV")
        else:
            pass
        # return render_template("index.html")
        return fiii.to_frame().to_html(table_id="table")
    else:
        return render_template("index.html")



@app.route("/getCSV")
def getPlotCSV():


    return Response(
        fiii.to_csv(encoding="UTF-8", sep="\t", header=True),
        mimetype="text/csv",
        headers={"Content-disposition":
                 f"attachment; filename={s_date}-{f_date}.csv"})


if __name__ == "__main__":
    app.run(debug=True,port=4444)

HTML:

<html lang="en"><head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/mate                                                                                                                                       rialize/1.0.0/css/materialize.min.css">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js                                                                                                                                       /materialize.min.js"></script>
    <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel                                                                                                                                       ="stylesheet">

    </head>
    <body>
        <div class="container">
            <div class="row">
                <form class="col s6 offset-s3" action="/" method="POST">
                    <div class="valign-wrapper col s12">
                        <h3 class="col s6">Query master</h3>
                        <div class="right-align input-field col s6">
                            <button class="btn btn-large btn-floating waves-                                                                                                                                       effect waves-light" type="submit" name="action">
                                <i class="material-icons right">send</i>
                            </button>
                        </div>
                    </div>

                    <div class="input-field col s12">
                        <input type="text" id="date-start" class="datepicker                                                                                                                                       " name="Start_date">
                        <label for="date-start">Start Date</label>
                    </div>

                    <div class="input-field col s12">
                        <input type="text" id="date-end" class="datepicker"                                                                                                                                        name="End_date">
                        <label for="date-end">End Date</label>
                    </div>

                    <label class="input-field col s12">
                        <input type="checkbox" name="lowercase" />
                        <span>Lowercase queries</span>
                    </label>

                    <label class="input-field col s12">
                        <input type="checkbox" name="sensitive" />
                        <span>Case sensitive</span>
                    </label>

                    <label class="input-field col s12">
                        <input type="checkbox" name="csv" />
                        <span>CSV export (Funkční pouze csv export)</span>
                    </label>

                    <div class="input-field col s12">
                        <textarea id="textarea1" name="query" class="materia                                                                                                                                       lize-textarea"></textarea>
                        <label for="textarea1">Queries (RegEx supported)</la                                                                                                                                       bel>
                    </div>

                </form>

            </div>

            <script>
                document.addEventListener('DOMContentLoaded', function() {
                    var elems = document.querySelectorAll('.datepicker');
                    var instances = M.Datepicker.init(elems, {
                        format: 'm/d/yyyy',
                    });
                });
            </script>
        </div>
    </body>
</html>

1 Ответ

1 голос
/ 28 января 2020

Ваша проблема не имеет абсолютно никакого отношения к ОО - это всего лишь результат использования глобальных переменных.

Ваш flask серверный процесс будет обслуживать все входящие запросы, один за другим. Итак, что происходит в многопользовательском сценарии:

1 / пользователь A отправляет index. Это присваивает значения вашим глобальным переменным s_date, f_date и fills.

2 / пользователь A перенаправляется на getCSV

3 /. Тем временем пользователь B отправляет сообщения на index. Это связывает ваши глобальные переменные s_date, f_date и fills с новыми значениями

4 / браузер пользователя A следовал перенаправлению и отображает fill пользователя B.

Решение довольно простое: НЕ используйте глобальное состояние для персистентности данных на пользователя - вам нужен пользовательский сеанс для короткоживущих данных сеанса и / или СУБД для долгоживущих пользовательских данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...