Przeglądaj źródła

feat: 单词上传

SongZihuan 3 lat temu
rodzic
commit
13c06e8a7e
6 zmienionych plików z 71 dodań i 12 usunięć
  1. 1 1
      app/app.py
  2. 2 2
      app/home.py
  3. 54 8
      app/test.py
  4. 1 0
      configure/__init__.py
  5. 3 1
      core/db.py
  6. 10 0
      templates/test.html

+ 1 - 1
app/app.py

@@ -51,7 +51,7 @@ class HEnglishFlask(Flask):
             return user.load_user(name, None)
 
         func = {"render_template": render_template}
-        for i in [400, 401, 403, 404, 405, 408, 410, 414, 500, 501, 502]:
+        for i in [400, 401, 403, 404, 405, 408, 410, 413, 414, 423, 500, 501, 502]:
             exec(f"def error_{i}(e):\n"
                  f"\treturn render_template('error.html', error_status={i}, error_info=e)", func)
             self.errorhandler(i)(func[f"error_{i}"])

+ 2 - 2
app/home.py

@@ -45,7 +45,7 @@ def index():
 def login():
     if not current_user.is_anonymous:
         current_app.logger.debug(f"re-login and abort(304)")
-        flash(f"You are login as {current_user.name}")
+        flash(f"You are login as {current_user.user}")
         abort(304)
 
     login_form = LoginForm()
@@ -68,7 +68,7 @@ def login():
 def register():
     if not current_user.is_anonymous:
         current_app.logger.debug(f"re-login and register(304)")
-        flash(f"You are login as {current_user.name}")
+        flash(f"You are login as {current_user.user}")
         abort(304)
 
     register_form = RegisterForm()

+ 54 - 8
app/test.py

@@ -2,13 +2,13 @@ from flask import blueprints, render_template, current_app, abort, redirect, url
 from flask import send_file
 from flask_login import current_user, login_required, logout_user
 from flask_wtf import FlaskForm
-from wtforms import StringField, SubmitField, BooleanField, PasswordField
+from wtforms import StringField, SubmitField, BooleanField, PasswordField, FileField
 from wtforms.validators import DataRequired, Length
 from app.user import UserWordDataBase
 from itsdangerous import URLSafeTimedSerializer
 from itsdangerous.exc import BadData
 from threading import Thread
-from typing import Optional
+from typing import Optional, List
 from core.word import Word
 import io
 
@@ -28,20 +28,37 @@ class ResetDeleteForm(FlaskForm):
     submit = SubmitField("Submit")
 
 
+class UploadFile(FlaskForm):
+    file = FileField()
+    submit = SubmitField("Upload")
+
+
 def __load_word(word):
     user: UserWordDataBase = current_user
     box, box_sum = user.get_box_count()
     search_from = SearchForm()
     reset_delete_form = ResetDeleteForm()
+    upload_form = UploadFile()
+    job: Upload = Upload.upload.get(user.user)
+    if Upload.upload.get(user.user) is not None:
+        if job.is_alive():
+            have_job = True
+        else:
+            flash("Upload finished")
+            have_job = False
+            del Upload.upload[user.user]
+    else:
+        have_job = False
+
+    template_var = dict(word=word, len=len,
+                        box=box, box_sum=box_sum, have_job=have_job,
+                        search=search_from, have_word=False, reset_delete=reset_delete_form, upload=upload_form)
+
     if word is None:
-        return render_template("test.html", word=word, len=len,
-                               box=box, box_sum=box_sum,
-                               search=search_from, have_word=False, reset_delete=reset_delete_form)
+        return render_template("test.html", **template_var)
     serializer = URLSafeTimedSerializer(current_app.config["SECRET_KEY"])
     word_id = serializer.dumps({"word": word.name})
-    return render_template("test.html", word=word, len=len,
-                           word_id=word_id, box=box, box_sum=box_sum,
-                           search=search_from, have_word=True, reset_delete=reset_delete_form)
+    return render_template("test.html", **template_var, word_id=word_id)
 
 
 @test.route("/")
@@ -213,3 +230,32 @@ def delete_user():
             user.delete_user()
         return redirect(url_for("test.question"))
     abort(400)
+
+
+class Upload(Thread):
+    upload = {}
+
+    def __init__(self, user: UserWordDataBase, file: List[str]):
+        super(Upload, self).__init__()
+        self.user: UserWordDataBase = user
+        self.file = file
+        self.upload[user.user] = self
+        self.daemon = True
+
+    def run(self):
+        for i in self.file:
+            self.user.import_txt(i)
+
+
+@test.route("/upload", methods=["POST"])
+@login_required
+def upload():
+    file = request.files["file"]
+    user = current_user._get_current_object()
+    job: Upload = Upload.upload.get(user.user)
+    if Upload.upload.get(user.user) is not None and job.is_alive():
+        flash("Please wait for the current task to complete")
+        return abort(423)
+    Upload(user, file.stream.read().decode('utf-8').split('\n')).start()
+    flash("File is being processed")
+    return redirect(url_for("test.question"))

+ 1 - 0
configure/__init__.py

@@ -12,6 +12,7 @@ conf = {
     "LOG_STDERR": True,
     "LOG_LEVEL": "DEBUG",
     "SERVER_NAME": None,
+    "MAX_CONTENT_LENGTH": 5 * 1024 * 1024,
 }
 
 

+ 3 - 1
core/db.py

@@ -7,6 +7,7 @@ import re
 import os
 import random
 import configure
+import time
 
 
 class DataBase:
@@ -209,10 +210,11 @@ class WordDatabase(DataBase):
         def response(self):
             return self._success, self._error, self._error_list
 
-    def import_txt(self, line: str):
+    def import_txt(self, line: str, sleep: int = 1):
         response = self.UpdateResponse()
         word_list = self.word_pattern.findall(line)
         for w in word_list:
+            time.sleep(sleep)
             try:
                 if self.find_word(w, True, True) is None:
                     self.__logger.debug(f"update word {w} fail")

+ 10 - 0
templates/test.html

@@ -179,6 +179,16 @@
                             </div>
                         </form>
 
+                        {% if have_job %}
+                            <p class="text-center"> Please wait for the current task to complete. </p>
+                        {% else %}
+                            <form method="post" action="{{ url_for("test.upload") }}" enctype="multipart/form-data" class="mb-2">
+                            {{ upload.hidden_tag() }}
+                            {{ upload.submit(class='btn btn-outline-primary mr-2') }}
+                            {{ upload.file(class="btn") }}
+                        </form>
+                        {% endif %}
+
                         <a class="col-12 btn btn-outline-danger mr-2 mb-2" data-toggle="modal" data-target="#LogoutModal"> LOGOUT </a>
                         <a class="col-12 btn btn-danger mr-2 mb-2" data-toggle="modal" data-target="#ResetModal" > RESET/DELETE USER </a>
                     </div>