人生シーケンスブレイク

シーケンスブレイク(Sequence breaking、シークエンスブレイクとも)とは、テレビゲームにおいて開発が想定している攻略ルートを逸脱し、ショートカットする行為のことである。

Django 2.x で Haml ライクな Bootstrap 4 を使う

Django記事シリーズ

の2つ目。

Django 2.x で Haml ライクなテンプレートを使う - 人生シーケンスブレイクdjango-hamlpyまで導入したものとする。

npm でパッケージ管理をする

JavaScript周りのパッケージは今後も入れる予定なので、npmでパッケージ管理を行う。

# packege.json ファイル生成
$ npm init

# パッケージインストールコマンド
$ npm install --save bootstrap

# bootstrapに必要な追加ライブラリもインストールする
$ npm install --save popper.js
$ npm install --save jquery

お好みで Font Awesome も入れてもいいと思う。

$ npm install --save font-awesome

インストールすると、/node_modules 以下にパッケージが入る。インストールしたパッケージはpackage.json, package-lock.json内にバージョンと共に保持される為、別環境では$ npm installコマンドを叩くだけで同バージョンがインストールされるようになる。

{
  "name": "django-test",
  "version": "1.0.0",
  "lockfileVersion": 1,
  "requires": true,
  "dependencies": {
    "bootstrap": {
      "version": "4.0.0",
      ...
    },
    "popper.js": {
      "version": "1.14.1",
      ...
    },
    "jquery": {
      "version": "3.3.1",
      ...
    },
    "npm": {
      "version": "5.7.1",
      ...

ライブラリをstaticアクセス可能にする

settings.py を編集し、/node_modules 以下のライブラリファイルに対して、/static/* でアクセス可能にする。

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/
STATIC_URL = '/static/'
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static'),
    os.path.join(BASE_DIR, 'node_modules'),
]

今回は /node_modules 以下はクライアント向けのライブラリしか利用していない & 簡略化の為にまるごと公開しているが、個別に公開してよりセキュアにしてもよいかも知れない。

ちなみに、Docker上で、ローカルの node_modulesとDockerコンテナ上のnode_modulesを共有したい場合には以下のように、 node_modules をマウントすればOK.

以下の例は docker-compose.yml + Dockerfileの構成。

  web:
    build: .
    command: python3 /code/manage.py runserver 0.0.0.0:8000
    ports:
      - '8080:8000'
    volumes:
      - ./mysite:/code
      - /code/node_modules
FROM python:alpine

ENV RUNTIME_PACKAGES="gcc musl-dev nodejs"

RUN apk --update add $RUNTIME_PACKAGES

RUN mkdir /code
WORKDIR /code

COPY mysite /code/

# for Django
RUN pip3 install -r /code/requirements.txt

# for Bootstrap
RUN npm install --verbose

Hamlファイルを編集する。

まずベースとなる base.html.haml を作り、ヘッダーやフッターはincludeして共通部分を作る。

layouts/base.html.haml

- load static

!!! 5
%html{ lang: 'ja' }
  %head
    %meta{ charset: 'utf-8' }
    %meta{ name: 'viewport', content: 'width=device-width, initial-scale=1, shrink-to-fit=no' }
    %title
      - block title
        ああああ
    %link{ rel: 'stylesheet', type: 'text/css', href: "{% static 'font-awesome/css/font-awesome.min.css' %}" }
    %link{ rel: 'stylesheet', type: 'text/css', href: "{% static 'bootstrap/dist/css/bootstrap.min.css' %}" }
    - block stylesheets

  %body
    - include 'layouts/_header.html.haml'

    .main.container-fluid
      - block main

    %script{ src: "{% static 'jquery/dist/jquery.min.js' %}" }
    %script{ src: "{% static 'bootstrap/dist/js/bootstrap.min.js' %}" }
    - block javascripts

_header.html.haml

ヘッダー部分。 ちなみにhamlpyでハイフンを含むプロパティを宣言する場合には、'data-toggle': 'collapse' のようにクォートで括ればOK.

%header.header.navbar.navbar-expand-md.navbar-light.bg-light
  %a.navbar-brand{ href: "#" }
    Navbar
  %button.navbar-toggler.hidden-md-up{ type: 'button', 'data-toggle': 'collapse', 'data-target': '#navbar-text', 'aria-controls': 'navbar-text', 'aria-expanded': 'false', 'aria-label': 'Toggle navigation' }
    %span.navbar-toggler-icon

  .collapse.navbar-collapse#navbar-text
    %ul.navbar-nav.mr-auto
      %li.nav-item
        %a.nav-link{ href: "{% url 'polls:index' %}" } Poll


    %form.form-inline
      %input.form-control.mr-sm-2{ type:'search', placeholder: 'Search', 'aria-label': "Search" }
        %button.btn.btn-outline-success.my-2.my-sm-0{ type: "submit" }
          Search

index.html.haml

メイン部分。base.html.hamlをextendsすることで呼び出す。

- extends 'layouts/base.html.haml'

- block main
  - if latest_question_list
    %ul
      - for question in latest_question_list
        %li
          %a{ href: "{% url 'polls:detail' question.id %}" }
            = question.question_text
  - else
    %p
      No polls are available.

ブラウザから確認

以下のようになっていればOK. f:id:ShineSpark:20180322203912p:plain

上手くいかない場合には、Chromeの開発者ツールでJSやCSSが正しく読み込まれてれているかチェックすると良い。

f:id:ShineSpark:20180322204451p:plain

参考として、↓のリポジトリソースコードを公開しています。 github.com

みんなのPython 第4版

みんなのPython 第4版