Djangoやるなら「現場で使える 基礎 Django」 Djangoビギナーが理解を深めるためのマストな一冊

Django 習得にあたり

Django を習得する上で、これまでは日本語による書籍がほとんど無かったのが辛いところでした。 しかし、ここ最近の Python界隈の盛り上がりに伴い、少しずつ Django 関連の技術書が増えてきたように思います。
とはいえ、やはり入門の入門という位置づけのものが多く、実践で使える情報は Web でひたすら検索するしかないのが現状でした。

そんな中、いつもお世話になっているakiyoko blogから出された「現場で使える 基礎 Django」が本当に実践的で、現場で Django を使い始めた方にオススメです。
技術書典で販売された同人誌ということで、技術書として物理的な厚みはないですが、内容はホントに濃い。

booth.pm

この本は、B5サイズ・148ページの 本格的な Django 解説書 です。

Django を仕事の現場で6年ほど使っている私が、日本語で書かれた書籍が少なくてずっと困っていたので自ら書きました。「現場でこんな本があったらなぁ」という想いで書いたので、仕事で使っているあなたにぴったりな本に仕上がっている はずです。

実践的と感じた理由は、Django の各機能が具体的にどんな用途で使われるか、裏でどんな動きをしているか、などの解説があり、 Django公式のチュートリアルをなぞって動くものができた、じゃあそこからどう理解を深めていくか、という場合に一歩踏み込んだ内容が習得できる形になっていることです。

書店には置いてありませんので立ち読みはできませんが、内容に関してakiyoko blogさんの記事で詳しくまとめられていますので、自分のスキルと照らし合わせることができます。

さらに発展形として

「現場で使える 基礎 Django」にはテストに関してなど、触れられていない部分があります。 それらを補足していくのにオススメなのがやっぱり Two Scoops of Django ここでどうしても英語書籍になってしまう。
絶対英語読みたくないマンには無理でしょうけれども、サンプルコード読むだけでも理解が深まる。かなり網羅的で実践的です。

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)

補足

Python 自体の習得も含めて学習したい人はPyQ、良いです。
もちろん Django のコースもあります。 運営も Python 界隈では有名なビープラウド。 オンライン学習で 2,980円/月 って高く感じてしまうんですが、一ヶ月だけ集中してやれば書籍買うのと同じです。 短期集中で出来る人はこれやっとけばいいかもしれない。 pyq.jp

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