経緯
ウェブ制作の一環として、コンタクトフォームを作ることになったのですが、既にある物を使うくらいなら勉強にもなるし、1から作ろうと考え他のがきっかけです。
実際、phpなどを使う方法もあるのですが、pythonに慣れていたため、flaskを使おうと思いました。
アーキテクチャ
参考にしたサイト
CSSフレームワーク:
- Bulma
Flaskでは:
- Jinja2の使い方がわかるとFlaskを用いた開発がよりスマートになる
- Flask-Mail documentation
- Attaching content and links to messages (Slack)
HTMLの中身
HTMLで必要になってくるのはformタグ
内のmethod
とaction
の指定であり、コンタクトフォームであるので下記のように記します。
<form id="contact-form" method="POST" action="/127.0.0.1:5000">
今回はFlaskを使用しているため、actionの指定先はFlaskを立ち上げるサーバになります。
したがって、htmlの中身は下記のようになります:
<form id="contact-form" method="POST" action="/127.0.0.1:5000">
<div>
<div class="field">
<label class="label">Name</label>
<div class="control">
<input name="name" class="input" type="text" placeholder="Name" required>
</div>
</div>
<div class="field">
<label class="label">Email</label>
<div class="control">
<input id="email" name="email" class="input" type="email" placeholder="Email" required>
</p>
<p id="email-error" class="help is-danger email-success">
This email is invalid
</p>
</div>
<div class="field">
<label class="label">Message</label>
<div class="control">
<textarea name="message" class="textarea" placeholder="Textarea" required></textarea>
</div>
</div>
<div>
<div class="control">
<button id="submit" class="button is-link">Submit</button>
</div>
<div class="control">
<button id="cancel" class="button is-text">Cancel</button>
</div>
</div>
</div>
</form>
<div id="result"></div>
簡略化のために氏名・メールアドレス・メッセージだけにしました。ここで重要になるのが、input
とtextarea
とbutton
なので、他の要素はとりあえずは無視します。
jsの中身
まず、フォームの中身をオブジェクト型で取ってきます
var form = document.forms.contactForm;
これを使用して、もしsubmitボタンが押された時、それらをajaxで処理します。
ajaxの部分について
初めに、デフォルトではsubmit
をした時にデフォルトでPOSTするようになっているのでこれをしないように明言する必要があります。
$(form).submit(function(e) {
// prevent it from POSTing
e.preventDefault();
//ここに必要なコードを記述していく
}
では実際に内容を書いていきます。
ajaxのdata
は正規化されていないといけないので、下記のように正規化を行う。
var formData = $(form).serialize();
そしてこれを用いて、ajaxに渡す内容は下記のようになります。
$.ajax({
type: 'POST',
url: 'http://127.0.0.1:5000',
data: formData
})
url
はflaskで指定する番号になるため、とりあえずはこのままにしておきます。実際にサーバがあるのならそれをここに記述します。
成功時
.done(function(response) {
// ここに成功時の動作を記述する
})
失敗時
.fail(function(response) {
// ここに失敗時の動作を記述する
});
jsのまとめ
したがって、以上のコードをまとめると下記のようになります:
// Object of the form
var form = document.forms.contactForm;
/*
* This function receives the form and sends it
* using ajax.
*/
function sendForm(e) {
// When 'submit' was clicked
$(form).submit(function(e) {
// prevent it from POSTing
e.preventDefault();
var formData = $(form).serialize();
$.ajax({
type: 'POST',
url: 'http://127.0.0.1:5000',
data: formData
})
// If succeeded, show a popup message
.done(function(response) {
// reset form inputs
$('form :input').val('');
})
.fail(function(response) {
// 失敗時の記述
});
});
};
form.name.addEventListener('change', sendForm, false);
となる。私は成功時は更にポップアップメッセージを追加し、失敗時はそのエラーを吐くようにしました。
色々工夫の方法はあると思うので、自由に書いてください。
Flaskの中身
pythonコードのでは実際にslackやメールを送信するという動作を行います。
メールは flask_mail
を使用すると実装ができ、slackは slackweb
というパッケージを使用すると実装ができます。
flask_mail
上記でも参考サイトであげさせていただいたFlask-Mail documentationを参考に送信するメールのコードを記述するとできます。
単純にメールを送信するコードは下記のようになります:
from flask_mail import Message
@app.route("/")
def send():
msg = Message('Hello',
sender='from@example.com',
recipients=['to_1@example.com', 'to_2@example.com'])
しかし、これでは同期処理となり、時間がかかるため、非同期処理にメールを送信する方法があります。
これを行うには、 threading
パッケージの Thread
メソッドを用います。
from threading import Thread
from flask_mail import Message, Mail
def send_async_mail(app, msg):
"""
Send mail asynchronously
"""
mail = Mail(app)
with app.app_context():
mail.send(msg)
def send_mail(email, app, html, sender, mail_title):
"""
Send mail to receiver
"""
msg = Message(
mail_title,
sender=('name', 'sender@example.com'),
recipients=[email],
bcc=[sender],
)
msg.html = html
thr = Thread(target=self.send_async_mail, args=[app, msg])
thr.start()
return True
とすれば、メールを非同期処理で送信することができます!
ここで、メールをhtmlでフォーマットしたい場合、Flaskはjinja2との相性が良いのでFlask-Mail documentationを参考にすると綺麗に作成できると思います。
Slack
今回、Slackには簡単にコンタクトフォームの内容を送信してみることにした。こちらはSlackが提供しているAPIですぐ実装ができます。
その前に、Slackにメッセージが送れるようにWebhook URLの発行が必要で、下記のサイトを参考にすると簡単にできます。
SlackのWebhook URL取得手順
URLを取得できればあとは簡単です。
Attaching content and links to messages (Slack)を参考に、好きな形でメッセージを送信します。
まず、メッセージの作成です。
def create_message():
attachments = []
attachment = {
'fallbacks': 'New Contact Has Arrived!',
'title': "New Contact Has Arrived!",
'color': '#anycolor',
'fields': [
{
'title': 'Date',
'value': date,
'short': True
},
{
'title': 'Name',
'value': name,
'short': True
},
{
# Any other fields
},
]
}
attachments.append(attachment)
return attachments
これでメッセージの作成ができました。あとは先ほど取得したwebhook urlを用いてメッセージの送信を行います。
import slackweb
slack = slackweb.Slack(url=WEBHOOK_URL)
def send_to_slack(slack):
slack.notify(attachments=format_attachment())
if __name__ == '__main__':
send_to_slack(slack)
以上で、メールとslackにメッセージを送信することができました!
最後に
コンタクトフォームを作る方法は色々あると思いますが、flaskを用いると結構簡単に作れてしまうことがわかりました。実際、色々な機能を追加するとまた違いますが、、、