Mezzanine には、REST API で Blog 投稿可能な、Plugin が存在します。
この Plugin は Client 側と、Service 側 package が存在します。
これらを install して、API を叩いてみた結果を記載します。
0. 前提
以下の環境で実行しています。
-
OS
CentOS release 6.7 (Final) -
Python Version
Python 2.7.8 -
Package (必要そうなものだけ抜粋)
Django (1.10)
Mezzanine (4.2.0)
1. Service の インストール
Mezzanine REST API - RESTful web API for Mezzanine CMS の、
Existing project
の手順を踏んでインストールしていきます。
1. pip インストール
pip install -U mezzanine-api
---------------------------------------------
Found existing installation: Django 1.10.2
Uninstalling Django-1.10.2:
Successfully uninstalled Django-1.10.2
Found existing installation: oauthlib 2.0.0
Uninstalling oauthlib-2.0.0:
Successfully uninstalled oauthlib-2.0.0
Found existing installation: requests 2.11.1
Uninstalling requests-2.11.1:
Successfully uninstalled requests-2.11.1
Found existing installation: Pillow 3.4.1
Uninstalling Pillow-3.4.1:
Successfully uninstalled Pillow-3.4.1
Found existing installation: pytz 2016.7
Uninstalling pytz-2016.7:
Successfully uninstalled pytz-2016.7
Found existing installation: tzlocal 1.2.2
Uninstalling tzlocal-1.2.2:
Successfully uninstalled tzlocal-1.2.2
Found existing installation: bleach 1.4.3
Uninstalling bleach-1.4.3:
Successfully uninstalled bleach-1.4.3
Found existing installation: future 0.15.2
Uninstalling future-0.15.2:
Successfully uninstalled future-0.15.2
Successfully installed PyYAML-3.12 bleach-1.5.0 django-1.10.4 django-braces-1.10.0 django-filter-1.0.1 django-oauth-toolkit-0.11.0 django-rest-swagger-0.3.10 djangorestframework-3.5.3 future-0.16.0 mezzanine-api-0.5.0 oauthlib-1.1.2 pillow-3.4.2 pytz-2016.10 requests-2.12.4 tzlocal-1.3
--------------------------------------------
そして、Django の Version が 上がっていて嫌な臭いがしますが、進めます。
2. settings.py に Application を追加
記載されている通り、mezzanine_api
、 rest_framework
、 rest_framework_swagger
、 oauth2_provider
を追加します。
INSTALLED_APPS = (
'mezzanine_api',
'rest_framework',
'rest_framework_swagger',
'oauth2_provider',
...
)
3. settings.py の MIDDLEWARE_CLASSES の一番上に、mezzanine_api.middleware.ApiMiddleware
を追加します。
MIDDLEWARE_CLASSES = (
'mezzanine_api.middleware.ApiMiddleware',
...
)
4. LOCAL SETTINGS
の直前に、 REST API SETTINGS
を追加します。
#####################
# REST API SETTINGS #
#####################
try:
from mezzanine_api.settings import *
except ImportError:
pass
5. Mezzanine 4.1.0以上は、urls.py
の 29行目に以下のコードを追加します。
version 3 から引き継いで使っているので、この辺りはだいぶずれています。
どこを指しているのかわからず、
if settings.USE_MODELTRANSLATION:
の直後に追加しました。
if settings.USE_MODELTRANSLATION:
urlpatterns += [
url('^i18n/$', set_language, name='set_language'),
]
# REST API URLs
urlpatterns += [
url("^api/", include("mezzanine_api.urls")),
]
6. Migration を実行
python2.7 manage.py migrate
----------------------------
Operations to perform:
Apply all migrations: admin, auth, blog, conf, contenttypes, core, django_comments, forms, galleries, generic, oauth2_provider, pages, redirects, request, robots, sessions, sites, twitter
Running migrations:
Applying auth.0008_alter_user_username_max_length... OK
Applying oauth2_provider.0001_initial... OK
Applying oauth2_provider.0002_08_updates... OK
Applying oauth2_provider.0003_auto_20160316_1503... OK
Applying oauth2_provider.0004_auto_20160525_1623... OK
----------------------------
7. HTTP サーバ再起動
service httpd restart
2. client_id、 client_secret の発行
インストール完了後、http://${yourdomain}/api/docs
にアクセスすると、
以下の画面が表示されます。
画面が出ています。
最初これで上手くインストールができたと喜んでいたのですが、
ブラウザの開発者コンソールを開くと、
おもいきり javascript error
が出力されていたので、
collectstatic
で 静的ファイルをコピーしました。
python2.7 manage.py collectstatic
collectstatic
実行後は、以下の通りの画面が表示されます。
インストール、設定がうまくいったようなので、
client_id
、client_secret
を発行します。
-
API Docs の OAuth App Manager リンクをクリックします。
-
Username
、Password
を入力し、Log in
をクリックします。
-
Click here
をクリックします。
-
Client SDK - Mezzanine REST API に従って、
各項目を入力して、Save
をクリックします。- Name
Mezzanine Python Client と入力 - Cient id
自動生成されます。 - Client secret
自動生成されます。 - Client Type
Confidential
を選択 - Authorization grant type
Authorization code
を選択 - Redirect urls
https://httpbin.org/get
- Name
-
入力項目の意味は、デジタル・アイデンティティ技術最新動向(2):RFCとなった「OAuth 2.0」――その要点は? (1/2) - @IT が参考になりました。
-
https://httpbin.org
については、site-hhs が参考になりました。
mezzanine-client-python
内でhttps://httpbin.org
がハードコードされていて、redirectUrl
が固定されます。
3. Client の インストール
続いて Client
をRemote CLI - Mezzanine REST API の手順を踏んで、
インストールします。
1. pip インストール
pip install -U mezzanine-client
2. 設定
2.
で発行した、client_id
、client_secret
と、通信先のURLを設定します。
-
通信先 URL の設定
mezzanine-cli config api_url https://www.monotalk.xyz/api -------------------------------------- from configparser import ConfigParser as Parser, NoOptionError ImportError: No module named configparser --------------------------------------
import
エラーになったので、configparser
を インストールします。
再度、pip install configparser ------------------------- Installing collected packages: configparser Running setup.py install for configparser ... done Successfully installed configparser-3.5.0 -------------------------
mezzanine-cli
を実行します。
成功しました。mezzanine-cli config api_url https://www.monotalk.xyz/api ------------------------- Configuration updated successfully. -------------------------
-
client_id
の設定mezzanine-cli config client_id ${id} ------------------------- Configuration updated successfully. -------------------------
-
client_secret
の設定mezzanine-cli config client_secret ${secret} ------------------------- Configuration updated successfully. -------------------------
4. Client を使ってみる
1. mezzanine-cli posts list
を実行します。
mezzanine-cli posts list
-----------------------------------------------------
Please click to authorize this app: https://monotalk.xyz/..........
Paste the authorization code (args > code) from your browser here:
-----------------------------------------------------
authorization code
を発行します。
2. URLにアクセスして、Authorize
をクリック。
Json 文字列がレスポンスとして取得できるので、code 値をterminal にコピーすると、実行されます。
が以下のエラーが発生して、client がエラーになりました。
__init__() got an unexpected keyword argument 'lookup_type'
調べたところ、django-filter の lookup_type というパラメータがなくなったことが原因のようです。
Service 側の コード上で使用しているところがあったので、lookup_type
> lookup_expr
に変更します。
Error in the docs for lookup expressions ? - Google グループ
-
/usr/local/lib/python2.7/site-packages/mezzanine_api/views.py を編集
cd /usr/local/lib/python2.7/site-packages/mezzanine_api vi views.py
-
UserFilter
class UserFilter(django_filters.FilterSet): """ A class for filtering users. """ #username = django_filters.CharFilter(name="username", lookup_type='istartswith') username = django_filters.CharFilter(name="username", lookup_expr='istartswith') class Meta: model = User fields = ['username']
-
PostFilter
class PostFilter(django_filters.FilterSet): """ A class for filtering blog posts. """ category_id = django_filters.NumberFilter(name="categories__id") #category_name = django_filters.CharFilter(name="categories__title", lookup_type='contains') category_name = django_filters.CharFilter(name="categories__title", lookup_expr='contains') #category_slug = django_filters.CharFilter(name="categories__slug", lookup_type='exact') category_slug = django_filters.CharFilter(name="categories__slug", lookup_expr='exact') #tag = django_filters.CharFilter(name='keywords_string', lookup_type='contains') tag = django_filters.CharFilter(name='keywords_string', lookup_expr='contains') author_id = django_filters.NumberFilter(name="user__id") #author_name = django_filters.CharFilter(name="user__username", lookup_type='istartswith') author_name = django_filters.CharFilter(name="user__username", lookup_expr='istartswith') #date_min = django_filters.DateFilter(name='publish_date', lookup_type='gte') date_min = django_filters.DateFilter(name='publish_date', lookup_expr='gte') #date_max = django_filters.DateFilter(name='publish_date', lookup_type='lte') date_max = django_filters.DateFilter(name='publish_date', lookup_expr='lte') class Meta: model = Post fields = ['category_id', 'category_name', 'tag', 'author_id', 'author_name', 'date_min', 'date_max']
3. 再度mezzanine-cli posts list
を実行します。
mezzanine-cli posts list
----------------
File "/Library/Python/2.7/site-packages/mezzanine_client/cli.py", line 70, in posts_list
print(fmt.format(id=post['id'], title=post['title'], url=post['url']))
UnicodeEncodeError: 'ascii' codec can't encode character u'\u3092' in position 22: ordinal not in range(128)
----------------
unicode で エラーのようなので、対象箇所に
.encode('utf-8')
を追加します。def posts_list(offset, limit):
api = get_client()
published_posts = api.get_posts(offset=offset, limit=limit)
click.echo(click.style('Published Posts', bold=True))
fmt = '{id} <{title} {url}>'
for post in published_posts:
#print(fmt.format(id=post['id'], title=post['title'], url=post['url']))
print(fmt.format(id=post['id'], title=post['title'].encode('utf-8'), url=post['url'].encode('utf-8')))
4. 再度mezzanine-cli posts list
を実行します。
※やっと動きました。
mezzanine-cli posts list
----------------
Published Posts
159 <SonarQube SonarPython を 使って Python の静的解析をしてみる https://monotalk.xyz/blog/Try-static-analysis-of-Python-using-SonarPython/>
158 <SonarQube Javaプログラムの警告をOFFにする https://monotalk.xyz/blog/Turn-off-Java-program-warning-on-SonarQube/>
157 <OS X El Capitan に SonarQubeをインストール、日本語化までしてみる https://monotalk.xyz/blog/install-SonarQube-on-El-Capitan/>
156 <施設名から住所を検索するAPIとして、Google Place API を使う https://monotalk.xyz/blog/Use-the-Google-Place-API-as-a-facility-search-API/>
155 <PyCharm terminal からpythonスクリプトを実行できるようにする https://monotalk.xyz/blog/pycharm-terminal-%E3%81%8B%E3%82%89python%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%A7%E3%81%8D%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB%E3%81%99%E3%82%8B/>
154 <dropwizard の task で、 wicket の mount されたページのURL一覧を出力する https://monotalk.xyz/blog/dropwizard-%E3%81%AE-task-%E3%81%A7-wicket-%E3%81%AE-mount-%E3%81%95%E3%82%8C%E3%81%9F%E3%83%9A%E3%83%BC%E3%82%B8%E3%81%AEurl%E4%B8%80%E8%A6%A7%E3%82%92%E5%87%BA%E5%8A%9B%E3%81%99%E3%82%8B/>
153 <Wicket URLからバージョン番号 [?0] を消したい https://monotalk.xyz/blog/delete-version-number-from-url-on-wicket/>
152 <Django BooleanField で Null許可する https://monotalk.xyz/blog/BooleanFiled-Null-True-on-django/>
151 <django、DBシーケンスを作成、使用する https://monotalk.xyz/blog/genelate-db-sequence-on-django/>
150 <Django-extentions の admin_generator で admin.py を自動生成する https://monotalk.xyz/blog/genelate-admin-on-django/>
----------------
5. mezzanine-cli posts get
を実行します。
-
command
mezzanine-cli posts get 3
-
output
{ "updated": "2016-05-17T00:58:15.116627Z", "title": "djangoのsettings.py内で、LogHandler StreamHandlerのログ出力先を指定する", "url": "https://monotalk.xyz/blog/mezzanine-pagedown/", "short_url": "/blog/mezzanine-pagedown/", "tags": "", "excerpt": "........", "allow_comments": true, "comments": [], "slug": "mezzanine-pagedown", "content": "........", "publish_date": "2015-04-28T09:30:23Z", "user": { "username": "monotalk", "first_name": "kem", "last_name": "", "email": null, "is_staff": true, "id": 2 }, "featured_image": "", "comments_count": 0, "id": 3, "categories": [ { "slug": "django", "id": 6, "title": "django" }, { "slug": "python", "id": 1, "title": "python" } ] }
6. mezzanine-cli posts create
を実行します。
-
command
mezzanine-cli posts create \ --title='Test Post from API Client' \ --content='Test' \ --categories='Test,Fun'
-
output
HTTP 401 Unauthorized
401エラーが発生しました。どうも認証が上手く通っていないらしく、
それで動作しないようです。
ローカル環境だと、上手くいくのですが、リモートに対する POST リクエストが上手くいきません。
半日ほど費やしましたが、WSGIアプリケーションからAuthorizationヘッダーを参照する - スコトプリゴニエフスク通信 が原因でした。。
Apache の wsgi の設定ファイルに以下を追記します。
WSGIPassAuthorization On
7. mezzanine-cli posts create
を実行します。
-
command
mezzanine-cli posts create \ --title='Test Post from API Client' \ --content='Test' \ --categories='Test,Fun'
-
output
Blog post successfully published with ID #162
登録できました。
5. API のパーミッションについて
mezzanine-api/views.py at master · gcushen/mezzanine-api
で、permission_classes
で、各APIのパーミッションが定義されています。
permission_classes = [IsAdminOrReadOnly]
デフォルトだと、認証なしでも閲覧できる API もありますので、
利用用途によっては、内容を見直したほうがいいかもしれません。
常識的にまあそうだよねというパーミッション指定は行われていますが、
気にするのであればPermissions - Django REST framework
を参考に変更すればよいかと思います。
以上です。
コメント