LoginSignup
100
138

More than 5 years have passed since last update.

vue.jsのDjangoでの使い所

Last updated at Posted at 2018-02-14

vue.jsのDjangoでの使い所

私がつくっているkoredeee.comというウェブアプリではDjangoにバックエンドで使っていますが、フロントエンドはページによってreactとvueを使い分けています。それぞれに長所があると思って両方使っているのですが、今回はvueの話をします。

vueはreactに比べて柔軟な使い方ができる印象です。Django(APIではなくテンプレート)が吐き出したデータを受け取って要素をつくるような書き方ができます。そしてその結果感動するほどHTMLがすっきりするのです!!

DjangoとVueを一緒に使う

DjangoにVueを組み合わせる方法については私のを含め下記の記事が参考になるでしょう。

コード

例えばフォームを書く場合、Djangoテンプレートの{% for %}構文vueのコンポーネントでHTMLをすっきりさせられます

まずvueでinputのコンポーネントをつくります。クラス名はBootstrapを意識しています

form-group.vue
<template>
  <div class="form-group">
    <label
       :for="id">
      {{ label }}
    </label>
    <input
       :type="type"
       class="form-control"
       :placeholder="label"
       :name="name"
       :id="id"
       :autofocus="!!autofocus"
       :required="!!required">
  </div>
</template>

<script>
export default {
  props: ['type', 'id', 'name', 'label', 'autofocus', 'required'],
}
</script>

エントリからコンポーネントを呼び出します。ここまでは普通のvueです

index.js
import Vue from 'vue'
import FormGroup from './form-group.vue'
var vueApp = new Vue({
  el: '#vue-app',
  components: {
    FormGroup
  },
})

ここからがDjangoのテンプレートです。例えばログイン画面をつくるとしましょう。実際につくってみたい方は

が参考になります。

Djangoのviewから渡されたformを{% for field in form %}でfieldごとに繰り返します。fieldはlabel要素やinput要素に必要なidやnameについての情報(field.id_for_nameやfield.html_name)を持っています。これらをpropとしてvueコンポーネントに渡しています。

registration/login.html
{% load render_bundle from webpack_loader %}
<!doctype html>
<html lang="ja">
<meta charset="utf-8">
</head>
<body>

<div id="vue-app">
<form method="post" action="{% url 'accounts:login' %}">
 {% csrf_token %}
 {% for field in form %}
 <form-group
   type="{{ field.field.widget.input_type }}"
   id="{{ field.id_for_label }}"
   name="{{ field.html_name }}"
   label="{{ field.label }}"
   :autofocus="{% if forloop.first %}true{% else %}false{% endif %}"
   :required="{{ field.field.required|lower }}"
  ></form-group>
  {% endfor %}
  <button class="btn btn-primary" type="submit">{% trans 'Login' %}</button>
  <input type="hidden" name="next" value="{{ next }}" />
</form>
</div>

{% render_bundle 'main' %}
</body>
</html>

HTMLがすっきり書けると思いませんか!?


もうひとつ例をあげます。たとえばkoredeee.comのソースをみてください。BootstrapのNavbarのように階層の深くなる要素が、短い記述に置き換えられています。

次のコンポーネントを用意しています

navbar.vue
<template>
  <nav class="navbar navbar-expand-lg navbar-light bg-light">
    <a class="navbar-brand" :href="logo_url">
      <img :src="logo" width="30" height="30" alt="">
    </a>
    <button v-if="showToggleButton" class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>

    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto">
        <li class="nav-item" v-for="item in items">
          <a class="nav-link" :href="item.url">{{ item.text }}</a>
        </li>
      </ul>
    </div>
  </nav>
</template>

<script>
export default {
  props: {
    logo: {
      type: String,
    },
    items: {
      type: Array,
      default: function() {
        return []
      }
    },
    logo_url: {
      type: String,
      default: '/'
    },
    showToggleButton: {
      type: Boolean,
      default: true,
    }
  }
}
</script>

<style lang="scss">
$white : #ffffff;
.bg-light {
  background-color: $white !important;
}
</style>

おかげでhtmlには下記だけでNavbarがつくれます!

<Navbar
logo="{% static 'images/logo.png' %}"
:items="[
{% if not user %}{text:'{% trans "ログイン" %}', url:'{% url "accounts:login" %}?next={% url "todos:home" %}'},{% endif %}
{% if user %}{text:'{% trans "ログアウト" %}', url:'{% url "accounts:logout" %}?next={% url "home:home" %}'},{% endif %}
]"
></Navbar>

Djangoから得られる{% if user %}でユーザーがログインしているかに応じてボタンを変えるということまでやっています。

100
138
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
100
138