6.Dropboxのフォルダ一覧を作る – Pythonで始めるDropboxAPI

やっとここまで来ましたが、FlaskとDropboxAPIでDropboxフォルダのファイル一覧ページを作ってみましょう。

もくじ

1.概要
 今回書くことについての説明をします。
2.DropboxAPIについて
 DropboxAPIがどんなものか、どういう仕組みで動いているのかについて説明します。
3.DropboxAPIを使う準備をする
 pythonからDropboxAPIを使うために必要な環境の準備をします。
4.サンプルプログラムを作る
 3で作成した環境を使ってサンプルプログラムを作ります。
5.flaskを使ってウェブアプリを作成
 ウェブフレームワークのflaskを使ってウェブアプリを作る練習をします。
6.Dropboxのフォルダ一覧を作る <ー今回はコレ
 flaskを利用して、Dropboxのフォルダ一覧を表示するウェブアプリを作ります。
7.dotcloudで公開する
 PaaSのdotcloudを使い、6で作ったウェブアプリをデプロイすることでみんなに見てもらえるようにします。
8.参考
 参考にしたURLなど。

本記事のソースはGitHubにあります。


6.1. FlaskでDropboxフォルダ一覧

 さて、非常に長くなりましたが、やっとFlaskとDropboxAPIを使ってのフォルダ一覧の作成です。
 基本的な処理はこれまでに書いてきたDropboxAPIを使ってフォルダデータを取得する処理と、Flask+HTMLテンプレートを使って一覧を表示する処理を合わせればOKです。
 だたし、ここでは処理を簡単にするためセッション変数にアクセストークンなど全て入れ込んでます。
 実際には別途トークンでも発行してそれをセッション変数にいれ、DBにトークン、dropbox user id、access_token、access_token_secret、有効期限あたりを入れておいて使ったりすれば管理上も便利だと思います。
 あと、SECRET KEYのところは適当にランダムな文字列を、APP KEYとAPP SECRETは「3.DropboxAPIを使う準備をする」で登録したアプリのApp KeyとApp Secretを入れてください。

ファイルとディレクトリの構成
[text]
testapp
|– app.py
|– templates
|– list.html
[/text]

app.py
[python]
from flask import Flask, request, session, redirect, url_for,
render_template

import dropbox
import oauth.oauth as oauth

app = Flask(__name__)
app.secret_key="SECRET KEY"

APP_KEY = ‘YOUR APP KEY’
APP_SECRET = ‘YOUR APP SECRET’
ACCESS_TYPE = ‘app_folder’

sess = dropbox.session.DropboxSession(APP_KEY, APP_SECRET, ACCESS_TYPE)

@app.route(‘/list’)
def list():
request_token = session.get("request_token")
request_token_secret = session.get("request_token_secret")
access_token = session.get("access_token")
access_token_secret = session.get("access_token_secret")

if request_token is None or request_token_secret is None:
return redirect_authorize_url(url_for("list"))

elif access_token is None or access_token_secret is None:
authorized_token = get_access_token(request_token, request_token_secret)
if authorized_token is None:
return redirect_authorize_url(url_for("list"))

else:
sess.set_token(access_token, access_token_secret)

client = dropbox.client.DropboxClient(sess)
folder_metadata = client.metadata(‘/’)

return render_template(‘list.html’, items = folder_metadata["contents"])

def redirect_authorize_url(callback_url):
request_token = sess.obtain_request_token()
session["request_token"] = request_token.key
session["request_token_secret"] = request_token.secret

oauth_callback = request.url_root + callback_url[1:]
authorize_url = sess.build_authorize_url(request_token, oauth_callback=oauth_callback)
return redirect(authorize_url)

def get_access_token(request_token, request_token_secret):
request_token = oauth.OAuthToken(request_token, request_token_secret)
try:
access_token = sess.obtain_access_token(request_token)
session["access_token"] = access_token.key
session["access_token_secret"] = access_token.secret
return access_token
except dropbox.rest.ErrorResponse, r:
print r
return None

if __name__ == "__main__":
app.run(debug=True)

[/python]

templates/list.html
[html]
{% extends ‘layout.html’ %}
{% block body %}

<h3>files</h3>
<ul>
{% for item in items %}
<li>{{ item.path }}</li>
{% endfor %}
</ul>

{% endblock %}

[/html]

templates/layout.html
[html]
<!DOCTYPE HTML>
<html lang="ja">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="http://twitter.github.com/bootstrap/1.3.0/bootstrap.min.css">
<title></title>
</head>
<body>
{% block body %}{% endblock %}
</body>
</html>
[/html]

実行する。
[bash]
python app.py
[/bash]

ブラウザで http://localhost:5000/list にアクセスして、Dropboxの認証、アプリでの使用を許可する画面、ファイル一覧が表示されればOKです。

Screen Shot 2011 11 03 at 12 52 27 AM

処理の内容としては、以下のような流れです。

  1. http://localhost:5000/list にアクセスするとlist()が実行される。
    [python]
    @app.route(‘/list’)
    def list():
    [/python]
  2. session変数をチェックして、初回アクセス時はどれも空なので、Dropboxへ認証してもらうURLを作ってリダイレクトする。
    [python]
    request_token = session.get("request_token")
    request_token_secret = session.get("request_token_secret")
    access_token = session.get("access_token")
    access_token_secret = session.get("access_token_secret")
    if request_token is None or request_token_secret is None:
    return redirect_authorize_url(url_for("list"))
    [/python]
  3. Dropbox側で認証した「許可」を押した後は、戻ってくるURLとして指定したURLにリダイレクトされる。ここでは、url_for(“list”)に戻ってくる。
    [python]
    return redirect_authorize_url(url_for("list"))
    [/python]
  4. 今度はリクエストトークンがあるので、アクセストークンを取得する処理を実行する。
    [python]
    elif access_token is None or access_token_secret is None:
    authorized_token = get_access_token(request_token, request_token_secret)
    if authorized_token is None:
    return redirect_authorize_url(url_for("list"))
    [/python]
  5. アクセストークンが取得できたら、DropboxClientを生成し、フォルダ’/’のファイル一覧を取得する。取得後は、テンプレートのlist.htmlを使って出力する。
    [python]
    client = dropbox.client.DropboxClient(sess)
    folder_metadata = client.metadata(‘/’)

    return render_template(‘list.html’, items = folder_metadata["contents"])
    [/python]

DropboxのサンプルプログラムをFlaskにのせただけなので面倒なことはないと思います。

6-2. アップロード処理の追加

 フォルダ一覧だけでは面白くないので、アップロード処理も追加してみましょう。

app.py に追加
[python]
from werkzeug import secure_filename

@app.route("/upload", methods=["GET", "POST"])
def upload():
if request.method == "GET":
return render_template("upload.html")

else:
sess.set_token(session.get("access_token"),
session.get("access_token_secret"))

client = dropbox.client.DropboxClient(sess)

uploadfile = request.files["file"]
filename = secure_filename(uploadfile.filename)
response = client.put_file(‘/’ + filename, uploadfile.stream.getvalue())
return redirect(url_for(‘list’))
[/python]

templates/upload.html
[html]
{% extends ‘layout.html’ %}
{% block body %}

<form action="{{ url_for(‘upload’) }}" method="POST" enctype="multipart/form-data">
<p>
<input type="file" name="file" />
<input type="submit" value="Upload" />
</p>
</form>

{% endblock %}
[/html]

uploadの処理はaccess_tokenがあること前提の処理になってます。必要なら色々書き足してください。

6-3. デコレータ

 listもuploadもどちらも、アクセストークンが必要な処理になります。
 DropboxのAPIを利用してウェブアプリを作る場合、DropboxAPIを作るところ全てでアクセストークンが必要になりそうです。
 そんなときは、デコレータを使って以下のようにすると良い感じです。

デコレータ
[python]
from functools import wraps

def requires_oauth(f):
@wraps(f)
def decorated_function(*args, **kwargs):
request_token = session.get("request_token")
request_token_secret = session.get("request_token_secret")
access_token = session.get("access_token")
access_token_secret = session.get("access_token_secret")

if request_token is None or request_token_secret is None:
return redirect_authorize_url(request.path)

elif access_token is None or access_token_secret is None:
authorized_token = get_access_token(request_token, request_token_secret)
if authorized_token is None:
return redirect_authorize_url(request.path)

else:
authorized_token = oauth.OAuthToken(access_token, access_token_secret)
sess.set_token(authorized_token.key, authorized_token.secret)

return f(*args, **kwargs)
return decorated_function

[/python]

uploadをデコレータでラッピング
[python]
@app.route(‘/upload’)
@requires_oauth
def upload():

[/python]

こうすることで、他のURLルートでもDropboxでの認証が必要、またはaccess_tokenが必要になった場合に、@requires_oauthと追加してあげるだけで簡単に実装できます。

6.4. ソース

 これらのソースはGitHubにあります。参考にしてみてください。

次回

7.dotcloudで公開する