こんにちは、k_ukiです。現在卒業研究でDjangoを用いたwebアプリの開発を行っております。
その中で、ボタンを押すことでその文字列をクリップボードにコピーする機能を実装しました。今回はその実装方法について述べていきます。
また、この記事ではオブジェクトを出力する方法(通常のCRUDの処理)やルーティングなどの実装方法は省略いたします。
テンプレートの作成
以下は、ボタンを配置するページのコードです。
{% extends 'base.html' %}
{%block title%}提案結果 {%endblock%}
{% block content %}
<div class="container">
<div class="row">
<div class="col-lg-8">
<h2>提案結果</h2>
<h3>こちらのワードなどいかがでしょうか?</h3>
<table>
<tbody>
<!-- ここから -->
<!-- ワードを繰り返し出力 -->
{% for word in suggest_result %}
<tr>
<!-- viewに情報を送信するためのフォーム -->
<form action="{% url 'search_word' object.pk %}" method="post">
{% csrf_token %}
<!-- ワードをボタンにして出力({{word}}に格納) -->
<td><input type="submit" name="copy_word" value="{{word}}"></td>
</form>
</tr>
{% endfor %}
<!-- 確認用のテキストフィールド(必要はありません) -->
<td><input type="text"></td>
<!-- ここまで -->
</tbody>
</table>
</div>
</div>
</div>
{% endblock content %}
記述について、一つひとつ解説していきます。
{% for word in suggest_result %}
ここでは、配列"suggest_result"に格納されたワードを一つずつ"word"に格納して出力できるようにしています。for文をテンプレートに書く際には"{% endfor %}"を忘れずに書きましょう。
<!-- viewに情報を送信するためのフォーム -->
<form action="{% url 'search_word' object.pk %}" method="post">
{% csrf_token %}
<!-- ワードをボタンにして出力({{word}}に格納) -->
<td><input type="submit" name="copy_word" value="{{word}}"></td>
</form>
ここでは、viewに値を送信するためのフォームを作成しています。
formタグの"action"では、formの送信先を指定しています。ここでは、'search_word'となっていますが、実際は"search_word/:pk"に送信していることになります。また、urlの:pkに該当する部分が"object.pk"になります。"search_word/:pk"というurlはボタンを表示させているページと同じurlになるため、ユーザーから見たら何も起きていないように見えます。
{% csrf_token %}
この記述によってcsrfトークンを同時に送信しています。Djangoではフォームを用いる際にはcsrfトークンを同時に送信する必要があります。
<input type="submit" name="copy_word" value="{{word}}">
この記述では、コピーしたい文字列が含まれたボタンを生成しています。
type="submit" とすることで、入力の形式をsubmitボタンに変更しています。また、submitボタンをクリックした時点でフォームが送信されます。"name"はそのボタンに対する名づけをしており、view側で何をコピーすれば良いか識別するために記述しています。最後に"value"では、ボタンを押下した際に送信したい文字列を指定しています。ここでは、for文で繰り返し出力できるようにしている"word"という変数をしています。
コピーをするために必要なモジュールをインストールする
Pythonでクリップボードを操作するために、「pyperclip」と呼ばれる外部モジュールを使用します。このモジュールはPython標準ではないため個別にインストールを行う必要があります。
pyperclip はpipコマンドでインストール可能です。
$ pip install pyperclip
viewで処理を記述する。
# views.py
import pyperclip
def detail_func(request, pk):
#ページを表示させる記述は省略
.....
.....
.....
if request.method == "POST":
if "copy_word" in request.POST:
pyperclip.copy(request.POST["copy_word"])
.....
view側では、送られてきたリクエストのhttpメソッドが"POST"だった場合の条件分岐をし、その中で実際の処理を記載していきます。
if "copy_word" in request.POST:
こちらでは、もし送られてきたPOSTのリクエストの中にcopy_wordという名前のものがあればという条件分岐をしています。"copy_word"とはテンプレート側のinputタグで記載したものです。つまり、この条件分岐によって、送られてきたリクエストがコピーをするものなのかを識別しているということです。
pyperclip.copy(request.POST["copy_word"]
ここで、実際コピーを行うためにpyperclipを使用します。pyperclip.copy()を使用することで簡単にクリップボードにコピーを行うことができます。引数に request.POST["copy_word"]を記述することで、送信されてきたPOSTメソッドのリクエストの中でも"copy_word"という名前のvalueを取得することができます。こうすることで、ボタンを押した箇所のvalueが自動的に格納され、その文字列がクリップボードにコピーされるのです。
さいごに
以上が、今回私の実装したテンプレートに表示したオブジェクトの文字列をクリップボードにコピーする方法です。今回の実装では、クリップボードにコピーする方法だけではなく、htmlのformタグの仕組みについても詳しく知ることができました!また、views.pyにおけるrequestの用途も知ることができました!!