return ("value":value_return, "destination":destination, "input":input, "error":error)
<textarea placeholder="例) aaa bbb">
JINJA2のフォーム入力後の確認HTMLの改鐔??縺??
置觸??で縺?htmlエスケープが觸??かり<br>がそのまま表示されてしまいダ繝?
{{ input | replace("\n", "<br>") }}
htmlエスケープ(HTMLエスケープ縺?<>&のみだった)
窶? 入力があれ縺?htmlエスケープ+改鐔??<br/>変觸??
窶? html表示はそのま縺?htmlエスケープ+改鐔??<br/>変觸??状態で出力
窶? DBにそのま縺?htmlエスケープ+改鐔??<br/>変觸??状態で出力入れる
窶? htmlフォーム内表示縺?htmlエスケープを解除し表示
↓
入力値はそのま縺?input変数に臀??持
confirm画面でエスケープ (html.escape()+改鐔??<br/>変觸??) しescape変数に臀??持
DB保存時に縺?escape変数にプラスしてダブ繝?/シング繝?/バッククォート、セミコロン、バックスラッシュをエスケープし保存
DBから藹??り出す際はそれらをアンエスケープしescape変数に臀??持
Docへ縺?input変数で臀??存
画面表示時はアンエスケープ (改鐔??<br />変觸??+html.unescape())
def escapeHtmlBr(text):
if text is None:
return text
elif isinstance(text, list):
list_escaped = [html.escape(item) for item in text]
list_escaped [item.replace("\n', '<br>') for item in list_escaped]
return list_escaped
else:
escaped_text = html escape(text)
return escaped_text.replace('\n', '<br>')
def unescapeHtmlBr(text):
if text is None:
return text
elif isinstance(text, list):
list_unescaped = [item.replace('<br>', '\n') for item in text]
list_unescaped = [html.unescape(item) for item in list_unescaped]
return list_unescaped
else:
text text.replace('<br>', '\n')
return html.unescape(text)
def escapeDB(text):
if text is None:
return text
elif isinstance(text, list):
list_escaped = [item.replace(';', ';') for item in text]
list_escaped = [item replace('"', '"') for item in list_escaped]
list_escaped = [item.replace("'", ''') for item in list_escaped]
list_escaped = [item.replace('\\', '\') for item in list_escaped]
list_escaped = [item.replace('`', '`') for item in list_escaped]
return list_escaped
else:
escaped_text = text.replace(';', ';')
escaped_text = escaped_text.replace('"', '"')
escaped_text = escaped_text.replace("'", ''')
escaped_text = escaped_text.replace('\\', '\')
escaped_text = escaped_text.replace('`', '`')
return escaped text
def unescapeDB(text)
if text is None
return text
elif isinstance(text, list):
list_unescaped = [item replace('`', '`') for item in text]
list_unescaped [item.replace('\','\\') for item in list_unescaped]
list_unescaped [item.replace(''', "'") for item in list_unescaped]
list_unescaped [item.replace('"', '"') for item in list_unescaped]
list_unescaped [item.replace(';', ';') for item in list_unescaped]
return list_unescaped
else:
unescaped_text = text.replace('`','`')
unescaped_text = unescaped_text.replace('\', '\\')
unescaped_text = unescaped_text.replace(''', "'")
unescaped_text unescaped_text replace('"', '"')
unescaped_text = unescaped_text.replace(';', ';')
return unescaped_text
■文字確鐔??
def check_special_characters(a):|
#チェックする記号のセット
special_characters = ['<', '>', '"', '&']
#特藹??の鐔??号が含まれているかをチェッ繧?
if any(char in a for char in special_characters):
raise ValueError(f"変謨? 'a' に軆??止されている文字が含まれています: {a}")
try:
a = "Hello & World"
check_special_characters(a)
except ValueError as e:
print(e)
■DB縺?null行の觸??髯?
bq = bigquery.Client()
sql = f"""SELECT a FROM `ds.b' WHERE c = '{pri}'"""
results=bq.query(sql)
list = list()
for row in results:
if row.a is not None:
list.append(str(row.a))
■Flask-WTF CCSRF対軆??縺?hiddenに入れる
https://qiita.com/RGS/items/c8c99970054a481ac80d
requrement.txt Flask-WTF==1.2.1
from flask_wtf import CSRFProtect
app = Flask(__name__)
app.config['SECRET_KEY'] = 'mysecretkey'
csrf = CSRFProtect(app)
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
PRGパターン縺?GETで藹??了画面に鐔??縺?がエラーとならない、WTF縺?POSTのみ利縺?ようだ
●完了画面でセッション藹??数がない場合はエラーとする
保存処理縺?doc_idをセッション藹??数に入れ
不正で直接完了画面にい縺?とエラーとする
https://xxxx.com/complete?doc id=ddd
■重複登録の回避軆??(PRG方藹??+JSボタン無蜉?)
・リダイレクト POST/Redirect/GET パター繝?
・連打を避けるためボタン縺?JS無効化
片方のみのためquerySelectorAll() を使う>ページ遷移しな縺?なった>下記JSを使う
@app.route('/submit', methods=['POST'])
def page():
page = model
if complete:
session['doc_id'] = page['input']['doc_id']
redirect(url_for('thank_you'))
else:
retrun template('layout.html')
@app.route('/thank_you')
def thank_you():
if 'doc_id' in session:
page['input']['doc_id"] = session['doc_id"]
session clear()
return render_template('complete_layout.html', page=page)
else:
return render_template('error.html", message="missing arg")
@app.errorhandler(404)
def page_not_found(e)
return render_template('error html', message="Page not found"), 404
error.html蛛?
<h1>{{message }}</h1>
submit蛛?
連打を避けるためボタンの無効化
片方のみのためquerySelectorAll() を使うとページ遷移しな縺?なる等がある
<script>
document.addEventListener('DOMContentLoaded', function(){
const form = document.getElementById('form');
const buttons = form.getElementsByTagName('button');
form.onsubmit= function(event) {
//クリックされたボタンを藹??得
const clickedButton = event.submitter;
//隠しフィールドを追加して、ボタン縺?name 縺? value を送菫?
const hiddenField = document.createElement('input');
hiddenField type = 'hidden'
hiddenField.name = clickedButton.name;
hiddenField.value = clickedButton value;
form.appendChild(hiddenField);
// すべてのボタンを無効化して臀??重送信を防止
for (let i = 0; i < buttons.length; i++) {
buttons[i].disabled = true;
}
}
}
</script>