Django / Python な人が Heroku で MySQL を使うときに環境変数 DATABASE_URL の末尾に “?reconnect=true” は不要

ググると大体 Rails の話

アプリを初めてHerokuにデプロイする場合、
手順をググると大体が、
CLEARDB_DATABASE_URL= 'mysql://[username]:[password]@[hostname]/[db_name]?reconnect=true'の値を、
DATABASE_URLという環境変数にコピーしなさい。
その場合、mysql://mysql2://に変更すること、とよく書いてある。

そのmysql2://は、よくよく読むと Ruby / Rails 固有の設定ということがわかるので、
Django の場合は変更せずそのままコピーで良いのかと思い、そのまま migrate しようとするとエラー。

TypeError: __init__() got an unexpected keyword argument 'reconnect'

どうするか

これに関してはここに記載があった。
ClearDB MySQL | Heroku Dev Center

末尾のパラメータ“?reconnect=true”Rails ユーザーの為のものなので

DATABASE_URL= 'mysql://[username]:[password]@[hostname]/[db_name]?reconnect=true'

DATABASE_URL= 'mysql://[username]:[password]@[hostname]/[db_name]'

に変更すると無事にマイグレート完了。

<広告>
改訂版出ましたね。

エキスパートPythonプログラミング改訂2版

エキスパートPythonプログラミング改訂2版

Djangoの名前空間 [name], [namespace], [app_name] の違いについて

はじめに

以下ソースコードの記述例は執筆時において主流である Django1.11 でのものとなっています。 先日 Django2.0 がリリースとなりURLまわりの書き方が変更となりましたが、名前空間の扱いには変わりが無いと認識しています。

役割の違い

nameとはURLパターンに付ける名前

url(r'^$', views.IndexView.as_view(), name='index')

テンプレートから {% url 'index' %}
ビューからreverse('index') のように逆引きで参照できます。

namespace = includeする側の urls.py で指定するプロジェクトにおける名前空間

url(r'^polls/', include('polls.urls', namespace='polls'))

テンプレートから {% url 'polls:index' %} ビューからreverse('polls:index') のように参照できます。
上記では polls/ 配下のURLは "polls" という名前空間になります。

app_name = includeされたアプリ側の urls.py で指定するプロジェクトにおける名前空間

app_name = 'polls'
urlpatterns = [
...
]

テンプレートから {% url 'polls:index' %} ビューからreverse('polls:index') のように参照できる。
上記の urlpatterns に書かれたパスは "polls" という名前空間になります。

こうすることで後々URLが変更になった場合などに修正が容易になります。 こうしてみると namespace と app_name は同じ機能であるようですが、名前空間の指定方法が2種類あるのはなぜか?

調べてみた

どうやら、Django1.9になった際に元々あったnamespaceに対しapp_nameの記法が追加されたよう。

Django 1.9 release notes | Django documentation | Django

The app_name argument to include() has been replaced by passing a 2-tuple (as above), or passing an object or module with an app_name attribute (as below). If the app_name is set in this new way, the namespace argument is no longer required. It will default to the value of app_name.

上記の例と同様ですが、公式ドキュメントの例でいうと
〜Django1.8:
mysite/urls.py

urlpatterns = [
    url(r'^polls/', include('polls.urls', namespace="polls")),
    ...
]

Django1.9〜:
mysite/urls.py

urlpatterns = [
    url(r'^polls/', include('polls.urls')),  # 'namespace="polls"' removed
    ...
]

polls/urls.py

app_name = 'polls'  # added
urlpatterns = [...]

さらに

とあります。これについては下記のようになります。

アプリケーションの名前空間

デプロイされているアプリケーションの名前を示します。 単一のアプリケーションのすべてのインスタンスは、同一のアプリケーション名前空間を持ちます。

インスタンス名前空間

アプリケーションの特定のインスタンスを識別します。 インスタンス名前空間は、プロジェクト全体で一意である必要があります。ただし、インスタンス名前空間は、アプリケーション名前空間と同じにすることができます。これは、アプリケーションのデフォルトインスタンスを指定するために使用されます。

名前空間のURLが与えられると、下記のルックアップを試みます。

  1. アプリケーションの名前空間との一致を検索する
  2. 現在のアプリケーションが定義されていれば、そのインスタンスに対しURL解決をする
  3. 現在のアプリケーションがない場合、デフォルトのアプリケーションインスタンスを探す
  4. デフォルトのアプリケーションインスタンスがない場合、アプリケーションの最後にデプロイされたインスタンスを利用する
  5. 提供された名前空間がステップ 1 のアプリケーション名前空間と一致しない場合、インスタンス名前空間のルックアップを試みる

あとがき

Djangoをやるなら必読の「Two Scoops of Django」の1.11版が出ています。
英語アレルギーがない方はぜひ。

Two Scoops of Django 1.11: Best Practices for the Django Web Framework (English Edition)

Two Scoops of Django 1.11: Best Practices for the Django Web Framework (English Edition)

【Alexaスキル開発】初期設定時エンドポイントの設定でエラーが発生した

Alexaスキル開発やってみた

ついに日本での発売が決定した Amazon Echo.

Alexa blog の Alexaスキル開発トレーニングシリーズ 第1回 初めてのスキル開発
を参考にそのまんまの形で設定を進める。

基本的には素直に進めれば問題ないと思うが、実際の画面とトレーニング内容で画面設計が変わっていて途中でエラー発生、立ち往生してしまったのでメモ。

開発を始めるには
- Amazon Developerアカウント
- AWSアカウント
が必要。

開発者コンソールでスキルを作成するのだが、それに必要な関数をAWS Lambdaで作成する必要がある。

その際に下記の「トリガーの追加」手順が抜けてしまい、
f:id:kita83:20171108213927p:plain

開発者コンソールでのサービスエンドポイントのタイプ設定時にエラーが発生した。

Error: Please make sure that "Alexa Skills Kit" is selected for the event source type of arn:aws:lambda:ap-northeast-1:118870790779:function:MyFactSkill

きちんと設定してあげればサービスシュミレーターの実行で、発話させることが出来る。

俺: 宇宙の豆知識を開いて

Alexa: 知ってましたか?水星の一年はたった88日です。

うん、知らんかった。

プライム会員なら少しのあいだ値引きされるようです。

Amazon Echo (Newモデル)、ヘザーグレー (ファブリック)

Amazon Echo (Newモデル)、ヘザーグレー (ファブリック)

【参考】

Error: Please make sure that "Alexa Skills Kit" is selected for the event source type of ... · Issue #138 · rgraciano/echo-sonos · GitHub

Djangoのテンプレートに、Bootstrapのform-groupやform-controlを設定できないとき

DjangoでBootstrapをFormにうまく適用させられず、調べたのでメモ。

問題点

Modelから生成したフォーム(forms.py)を使ってテンプレートにフォームを表示させる際に、{{ form }}の形で自動生成している。

<div class="container" style="padding:20px 0">
  <form method="post" enctype="multipart/form-data" action="">
    {% csrf_token %}
    {{ form }}
    <div class="form-group text-right" style="padding:20px 0">
      <input type="submit" value="Submit" class="btn btn-primary"/>
    </div>
  </form>
</div>

その場合、<label><input>がないのでBootstrap固有のform-groupform-controlを設定できず、下のような素のフォームとなってしまう。
f:id:kita83:20170817224821p:plain

for文で普通にフォームを作成してみた

<div class="container" style="padding:20px 0">
  <form method="post" enctype="multipart/form-data" action="">
    {% csrf_token %}
    {% for field in form %}
      <div class="form-group">
        <label class="control-label" for="{{ field.name }}">{{ field.label }}</label>
        <div class="form-control">
          <input type="" class="form-control"
                 name="{{ field.name }}"
                 id="{{ field.name }}">
      </div>
    </div>
    {% endfor %}
    <div class="form-groupe text-right" style="padding:20px 0">
      <input type="submit" value="Submit" class="btn btn-primary"/>
    </div>
  </form>
</div>

うまく表示された。
f:id:kita83:20170817225833p:plain

これで正しく動作もしているようなんだけど、<input type="">って何も入れなくていいのか..
フィールドタイプが全て同じではないのでfield.***と動的に変えたいがそういったものがあるのか、指定の仕方がわからない。

結果的にforms.pyで指定できた

__init__で全てのフォームの部品のclassにform-controlを指定することで適用することができた。

class RestaurantForm(ModelForm):
    def __init__(self, *args, **kwargs):
        super(RestaurantForm, self).__init__(*args, **kwargs)
        for field in self.fields.values():
            field.widget.attrs["class"] = "form-control"

    class Meta:
        model = Restaurant
        exclude = ('user', 'date',)

上記のように、

for field in self.fields.values():
    field.widget.attrs["class"] = "form-control"

を追加して、{{ form }}だけの書き方に戻すと..

<div class="container" style="padding:20px 0">
  <form method="post" enctype="multipart/form-data" action="">
    {% csrf_token %}
    {{ form }}
    <div class="form-group text-right" style="padding:20px 0">
      <input type="submit" value="Submit" class="btn btn-primary"/>
    </div>
  </form>
</div>

初めの素のフォームではなく、Bootstrapが適用されるようになりました。

f:id:kita83:20170817231219p:plain

django-bootstrap-toolkit という便利ツールもあるよう

このツールを導入すると{{ form|as_bootstrap }}でいけるみたいです。

↓参考

Djangoで、ModelForm、Formのあれこれ - naritoブログ

DjangoでTwitterBootstrap使うならdjango-boostrap-toolkitがオススメ - Make組ブログ(移行して http://blog.hirokiky.org/ にあるよ)

<広告>
英語だけど、Djangoについてここまで体系的にまとめられているのってあまり無いんじゃないでしょうか。

Two Scoops of Django: Best Practices for Django 1.8

Two Scoops of Django: Best Practices for Django 1.8

最新のDjango本「Two Scoops of Django 1.11: Best Practices for the Django Web Framework」

PythonRubyPHPなんかと比べて日本語情報が少ないというのはよく聞く話です。

それはPythonの主要フレームワークであるDjangoに関しても同様で、
公式のチュートリアルはしっかり日本語化され懇切丁寧な内容となっているものの、
それ以外の書籍等に関しては「本命がない」という感じがします。

同じように、いわゆる「Django本がない」というのが下記の記事でも書かれています。

ベスト・オブ・Django本! - akiyoko blog

そこで紹介されていたのがこれ。(すみません、こちらにも貼らせて頂きます)

Two Scoops of Django: Best Practices for Django 1.8

Two Scoops of Django: Best Practices for Django 1.8

記事の紹介によりますと、それは充実しているらしいです。
丁寧に全目次の紹介や、出て来る英単語訳まで載せてくれていますよ。
ありがたや。

ベスト・オブ・Django本! - akiyoko blog

私が自信を持ってオススメできる ベスト・オブ・ Django本が「Two Scoops of Django: Best Practices for Django 1.8」 です!
残念ながら全編英語の本ですが、設計のベストプラクティスから細かな Tips まで詳細に分かりやすく解説されている Django の専門書です。

そしてこれが数多ある技術書に漏れず、なかなか良いお値段です。
思いがけずHuluから1,000円のAmazonクーポンもらったので、それを足しにして買おうかなと思っていたら・・

なんとですね、次が出てるんですよ。

Two Scoops of Django 1.11: Best Practices for the Django Web Framework

Two Scoops of Django 1.11: Best Practices for the Django Web Framework

でも2017年8月現在、在庫切れで買えないんです。
著者のページからはPDFでも買えるみたいです。
紙で欲しいんだけど、送料は高くつきそう。

Two Scoops of Django 1.11: Best Practices for the Django Web Framework – Two Scoops Press

ともあれ、読んでもいないのにあーだこーだ言ってもしょうがないので、
英語の勉強も兼ねて、じっくり取り組んでみようと思います。