When I implemented a project in Flask, In the public key registration form (Text Area) that led to "Copy & Paste", There was an end user who dropped a file. I thought that there were people who did that, but I investigated if I could manage it ... StackOverflow: Load Textfile via Drag and Drop on Textarea I found that.
I found that I could do simple JavaScript unexpectedly, so I implemented it in Flask.
Flask First, define the public key registration form in Flask as the FORM class RegistForm. Public key validation uses the sshpubkeys library, which is not the main subject.
It is a test application that just receives and displays the verified data of the form data.
import os
from flask import (
Flask,
request,
render_template,
redirect,
url_for,
)
from flask_wtf import FlaskForm
from wtforms import TextAreaField, SubmitField, ValidationError
from wtforms.validators import InputRequired
from sshpubkeys import SSHKey, InvalidKeyError, MalformedDataError
class RegistForm(FlaskForm):
pubkey = TextAreaField("PublicKey",validators=[InputRequired()])
submit = SubmitField("OK")
reset = SubmitField("RESET")
def validate_pubkey(self, field):
if field.data.find('\n') >1:
raise ValidationError("Too Many Publickey")
sshpubkey = SSHKey(field.data, strict=True)
if sshpubkey.key_type != b"ssh-rsa":
raise ValidationError("Invalid Key Type")
try:
sshpubkey.parse()
except InvalidKeyError as err:
raise ValidationError("Invalid PublicKey")
except MalformedDataError as err:
raise ValidationError("Malformed key Error")
except NotImplementedError as err:
raise ValidationError("Undefined Error")
app = Flask(__name__, static_folder='static')
app.config['SECRET_KEY']='12345678901234567890'
@app.route("/", endpoint="register", methods=["GET", "POST"])
def register():
form = RegistForm()
if request.method == "GET":
return render_template("test.html",
form=form,
endpoint="register")
if form.validate_on_submit():
return form.pubkey.data
else:
print(f'vaslidation error')
return redirect(url_for("register"))
if __name__ == "__main__":
app.run(
host=os.getenv("APP_HOST", "localhost"),
port=os.getenv("APP_PORT", 8080),
debug=True,
)
JavaScript
Prepare the following functions in static / functions.js.
function dropfile(file) {
var reader = new FileReader();
reader.onload = function(e) {
notepad.value = e.target.result.replace(/(?:\r\n|\r|\n)/g, '');
};
reader.readAsText(file, "UTF-8");
};
notepad.ondrop = function(e) {
e.preventDefault();
var file = e.dataTransfer.files[0];
dropfile(file);
};
I'm using a DataTransfer object, but not all browsers publish the object. If you have a modern browser, there should be no problem ...
HTML
Actually, this is the only thing that seems to be a knack. I have given the attribute id "notepad" to the field of the class defined in forms.py.
{% extends "base.html" %}
{% block contents %}
<form action="{{ url_for( endpoint ) }}" method="post">
{{ form.hidden_tag() }}
{{ form.pubkey(id="notepad", raws=6, cols=80,
placeholder="Copy&Past or Drag&Drop here!") }}
{{ form.submit }}
{{ form.reset }}
</form>
{% endblock contents %}
rows
, cols
, and placeholder
can be given to render_kw
in dictionary format in the class definition, but I think it's better not to define much related to drawing in the class.
render_kw={"rows": 6, "cols": 80, "placeholder": "Copy&Paste" }
This also has nothing to do with the main subject, but some people may be interested in it. For the time being, prepare such base.html.
{% from "_defaults.html" import render_htmlattribs, render_styles, render_scripts %}
{% block doc -%}
<!DOCTYPE html>
<html{% block html_attribs %} {{ render_htmlattribs() }}{% endblock html_attribs %}>
{%- block html %}
<head>
{%- block head %}
<title>{% block title %}{{ render_title() }}{% endblock title %}</title>
{%- block metas %}
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta charset="UTF-8">
{%- endblock metas %}
{%- block favicon %} {%- endblock favicon %}
{%- block styles %}
{{ render_styles() }}
{%- endblock styles %}
{%- endblock head %}
</head>
<body{% block body_attribs %}{% endblock body_attribs %}>
{%- block body %}
{% block contents %} {% endblock contents %}
{% block footer %}
{{ render_footer() }}
{%- endblock footer %}
{% block scripts %}
{{ render_scripts() }}
{%- endblock scripts %}
{%- endblock body %}
</body>
{%- endblock html %}
</html>
{% endblock doc -%}
The macro defined in _defaults.html looks like this: I'm using it all the time, so I try to load bootstrap and jquery, but You don't have to have this. All you have to do is load static / functions.js.
{% macro render_htmlattribs() -%}
lang="ja"
{%- endmacro %}
{% macro render_styles() %}
<link href="/static/bootstrap-4.5.2/css/bootstrap.min.css" rel="stylesheet">
<link href="/static/base.css" rel="stylesheet">
{% endmacro %}
{% macro render_scripts() %}
<script src="/static/jquery-3.5.1.min.js"></script>
<script src="/static/bootstrap-4.5.2/js/bootstrap.min.js"></script>
<script src="/static/functions.js"></script>
{% endmacro %}
<input type =" file "/>
, this will be helpful.
Read uploaded file as textRecommended Posts