Python Django + React

これは m3 での TeckTalk発表資料です。

Python Django
---

* django 公式  
  * https://www.djangoproject.com/

* django チュートリアル  
  * https://docs.djangoproject.com/ja/2.0/intro/



* 公式で日本語のドキュメントが整備されていて学習しやすい
* チュートリアルが丁寧でわかりやすい
* PythonでRailsのような手軽さでアプリが作れる


プロジェクトとアプリケーション
------

* プロジェクト
    * １つのwebシステムを構成する単位
    * 基礎設定を保持

* アプリケーション
    * model, view, template, マイグレーション定義を持つ
    * URLのパスに割り当てる感じで使うらしい
        * あるパス(例: `/app1`)の機能を作る感じ
    * この単位でpythonモジュールにして再利用可能にできる

プロジェクトとアプリケーション
------

mysite プロジェクトを作成

```bash
$ django-admin startproject mysite
```

mysite 内に polls アプリケーションを作成

```bash
$ cd mysite
$ python manage.py startapp polls
```

ファイル構造
------

```code
mysite/
    manage.py              # プロジェクトの操作用コマンド

    mysite/                # プロジェクトの基礎部分
        settings.py           # プロジェクト設定
        urls.py               # アプリケーション単位のrouting定義

    polls/                 # アプリその１: 投票アプリ
        admin.py              # 管理画面(django-admin)にモデルを登録
        apps.py               # アプリケーション単体の設定
        migrations/           # migraionスクリプトが自動で生成される場所
        models.py             # モデルを定義
        tests.py              # テスト実装場所
        urls.py               # polls の中のrouting定義
        views.py              # いわゆるControllerを実装するところ
        templates/
          polls/index.html    # htmlテンプレート

    accounts/              # アプリその２: 認証アプリ
        apps.py
        modeuls.py
        views.py
        ...
```

モデル
-------

```python:polls/models.py
class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')

class Choice(models.Model):
    # 結合関係定義
    question = models.ForeignKey(Question, on_delete=models.CASCADE)

    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)
```

* モデルにフィールドの定義を記述
* これをもとにマイグレーション用スクリプトを生成
* OneToOne, OneToMany, ManyToManyの関係を定義できる


views
-------

```python
def top_page(request):
  return render(request, 'toppage.html', {message: "Hello"})

# Question の一覧表示
class QuestionList(ListView):
    template_name = 'polls/index.html'
    model = Question
```

* Java, RailsでいうController
* 直接メソッドを定義してそれをURLに割り当てる
* クラスで実装する場合は基礎クラスが充実
    * モデルの一覧、詳細表示などに対応したクラス
    * `ListView`, `DetailView`

テンプレート
------

```html:polls/templates/polls/results.html
<h1>{{ question.question_text }}</h1>
<ul>
{% for choice in question.choice_set.all %}
    <li>{{ choice.choice_text | upper }}</li>
{% endfor %}
</ul>

<a href="{% url 'polls:detail' question.id %}">Vote again?</a>
```

* HTMLは専用のテンプレート表記で実装
* 実際にはPythonそのもののとは違う
* 例: スライスを直接は使えない
    * NG: `{{ choice.votes[1:2] }}`
    * OK: `{{ choice.votes | slice: "1:2" }}`


管理画面機能
-------

* 管理画面機能 `django_admin` が便利
* プロジェクトの初期テンプレートを作った段階で組み込み済み
* ユーザ、グループ、権限管理などを保持している
* CRUDを使った管理画面が簡単に作れる

```python
# polls/admin.py
from django.contrib import admin
from .models import Question

# QuestionモデルのCRUD 追加
admin.site.register(Question)
```

Javascriptと連携
------

DjangoとReactをセットにしたプロジェクトのテンプレートを公開してくださっているものがあるので利用すると楽。

* Django, React, Bootstrap 4 with Python 3 and webpack project boilerplate
    * https://github.com/vintasoftware/django-react-boilerplate/


djangoのURLルーティング定義をJavascriptで使う
------

djangoで定義したURLルーティングをJavascript内で使えるモジュールがある

* Javascript url handling for Django that doesn't hurt.
    * https://github.com/ierror/django-js-reverse

```javascript
<!-- routing定義をもつ Urls クラスを定義 -->
<script src="{% url 'js_reverse' %}" type="text/javascript"></script>

<script>
  $.ajax({
    <!-- URL取得 -->
    url: Urls.question_detail(12) # => "/questions/12"
  })
</script>
```

webpackとの連携
------

javascript の webpackと連携するためのライブラリ  

* Transparently use webpack with django
    * https://github.com/ezhome/django-webpack-loader

* webpackプラグイン `webpack-bundle-tracker`
    * webpackビルド結果をjsonファイルに逐次出力
* pythonモジュール `django-webpack-loader`
    * 上記jsonを読み取ってHTMLのscriptタグを出力

```json
{
  "chunks": {
    "main": [
      {
        "name": "main.js",
        "publicPath": "http://localhost:3000/assets/bundles/main.js",
        "path": "/Users/namu/dev/python/pytter/assets/bundles/main.js"
      }
  ...
```

Demo
------

* 管理画面へのCRUD追加方法
* モデルの定義の簡潔さと、データの取得方法
* ログイン要否設定とUser取得方法
* tweet_apiのコントローラの実装方法


まとめ
-----

* Python djangoが思ったより便利
* 「batteries included」の思想の通り機能が充実
* 特に管理画面の機能が強力

* 他の言語でも、実装方法を取り入れていきたい