GIG

赴くままに技術を。

Django1.9+Bootstrap3でログイン表示を作る

認証・認可は、Djangoに限らず、Webフレームワークを使い出してまず外せない機能。

Django公式マニュアルを見てみると、機能としてデフォルトで持っていて、それを用途に応じて拡張していく方針とのこと。 Users, Groupモデル、パスワードをハッシュ化して保持して保持するといった提供されている。

1回やり方を確認しておけば何にでも応用できそうなのででBootstrap3を利用し、ログイン画面を表示してみる。

環境

環境としては、こちら。

項目 バージョン
Python 3.5.1
Django 1.9.5
jQuery v2.2.2
Bootstrap v3.3.6

Djangoの認証

Djangoで認証・認可の機能は、django.contrib.authで使用できる。これはプロジェクトを生成するときに元から含まれている。プロジェクト作成後、マイグレーション(python manage.py migrate)とすると認証・認可用のテーブルが作成される。

つくってみる

はじめにプロジェクトから作成する。 radishはただのプロジェクトの例なので、適宜変更してください。

$ django-admin startproject radish
$ python manage.py migrate

次にaccountsdashboardアプリを作成する。 accountsには認証・認可機能を含めで、dashboardには認証された後のリダイレクト先のアプリを含める想定。

$ python manage.py startapp accounts
$ python manage.py startapp dashboard

アプリを作ったら、忘れずsettings.pyINSTALLED_APPSに追記しておく。これを忘れると、後で出てくるテンンプレートが存在しないというエラーが発生するので、忘れずに。

  • radish/radish/settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    # local
    'accounts.apps.AccountsConfig',
    'dashboard.apps.DashboardConfig',
]
Bootstrapを配置する

JavascriptCSSのライブラリは、radish/staticフォルダ内に入れておく。するとsettings.pyの下記の記載に沿って、参照可能となる。

  • radish/radish/settings.py
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.9/howto/static-files/

STATIC_URL = '/static/'

STATICFILES_DIRS = (
    os.path.join(BASE_DIR, "static"),
)

jQueryやらBootstrapやらをインストールする。それぞれダウンロードするのが面倒であったので、Bowerで入れる。

  • radish/static/
$ bower init
...
(対話型でbower.jsonを作成)
...
$ bower install jquery -S
$ bower install bootstrap -S
トップ画面、ログイン画面、ログイン後画面(ダッシュボード画面)を作る

各画面共通で使うNavbarなどはbase.htmlに記述し、他の画面はそれを継承する。またそういう共通のHTMLはradish/templates配下に入れておく。しかし、このパスはDjangoが見つけてくれないので、またsettigs.pyに追記する。

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],  # 追記箇所
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

それではbase.html{% load staticfiles %}と書くと、下のように{% static xxx%}でjsやcssを利用できる。{% if user.is_authenticated %}~{% else %}で条件分岐しているところは、認証されている場合のみ有効にするメニュー表示である。また {% block container %}~{% endblock %}は、base.htmlを継承した方のHTMLが埋め込まれる箇所となっている。

{% load staticfiles %}

<!DOCTYPE html>
  <html lang="ja">
    <head>
      <meta charset="utf-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1">

      <tile>{% block title %} Radish | {{ site_name }}{% endblock %}</tile>

      <!-- CSS -->
      <link href="{% static 'bootstrap/dist/css/bootstrap.min.css' %}" rel="stylesheet" />
      <link href="{% static 'bootstrap/dist/css/bootstrap-theme.min.css' %}" rel="stylesheet" />
      <link href="{% static 'font-awesome/css/font-awesome.css' %}" rel="stylesheet" />
  </head>
  <body>
    <nav class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
          <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
              <span class="sr-only">Toggle navigation</span>
              <span class="icon-bar"></span>
              <sapn class="icon-bar"></sapn>
              <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="#">Radish</a>
          </div><!-- /.navbar-header -->

          <div id="navbar" class="navbar-collapse collapse">
            {% if user.is_authenticated %}
              <ul class="nav navbar-nav navbar-right">
                  <li>
                      <a href="#">Dashboard</a>
                  </li>
                  <li>
                      <a href="#">Settings</a>
                  </li>
              </ul>
            {% else %}
              <form class="navbar-form navbar-right">
                  <button type="button" class="btn btn-primary"
                    onclick="location.href=&quot;{% url 'login' %}&quot;;">
                    Login</button>
              </form>
            {% endif %}
          </div><!-- /.navbar-collapse -->
        </div><!-- /.container -->
    </nav>

    {% block container %}
    {% endblock %}

    <hr/>
    <footer>
      <p>&copy; hermesian</p>
    </footer>

    <!-- JavaScript -->
    <script src="{% static 'jquery/dist/jquery.min.js' %}"></script>
    <script src="{% static 'bootstrap/dist/js/bootstrap.min.js' %}"></script>
  </body>
</html>

次にトップ画面home.htmlは下記。 これはBootstrapのjumbotronの例をそのまま利用。

{% extends 'base.html' %}

{% load staticfiles %}

{% block container %}
<!-- Main jumbotron for a primary marketing message or call to action -->
<div class="jumbotron">
    <div class="container">
      <h1>Radish</h1>
      <p>
          "Radish is a dashboard for collecting visualizing report."
      </p>
    </div>
</div>
<div class="container">
      <!-- Example row of columns -->
      <div class="row">
        <div class="col-md-4">
          <h2>Heading</h2>
          <p>Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui. </p>
          <p><a class="btn btn-default" href="#" role="button">View details »</a></p>
        </div>
        <div class="col-md-4">
          <h2>Heading</h2>
          <p>Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui. </p>
          <p><a class="btn btn-default" href="#" role="button">View details »</a></p>
       </div>
        <div class="col-md-4">
          <h2>Heading</h2>
          <p>Donec sed odio dui. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Vestibulum id ligula porta felis euismod semper. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.</p>
          <p><a class="btn btn-default" href="#" role="button">View details »</a></p>
        </div>
      </div>
  </div>
{% endblock %}

home.htmlのログインボタンで遷移する先は、accounts/tempalte/accounts/login.html<form>タグの下に{% csrf_token %}とあるのは、DjangoCSRF対策機能である。

{% extends 'base.html' %}

{% load staticfiles %}

{% block container %}
<div class="container">
  <div class="page-header">
      <h3>
        Login
      </h3>
  </div>
  <div class="row">
    <div class="col-md-4 col-md-offset-4">
        <div class="panel panel-default">
            <div class="panel-body">
                <form accept-charset="utf-8" role="form" action="{% url 'login' %}" method="post">
                    {% csrf_token %}
                    <fieldset>
                        <div class="form-group">
                            <input type="text" id="username" name="username" class="form-control"
                                   placeholder="Username" required autofocus>
                        </div>
                        <div class="form-group">
                            <input type="password" id="password" name="password" class="form-control"
                                   placeholder="Password" required>
                        </div>
                        {% if login_failed %}
                          <p class="text-danger">Sorry, that login was invalid.  Please try again.</p>
                        {% endif %}
                        <input class="btn btn-lg btn-success btn-block" type="submit" value="Log in">
                    </fieldset>
                </form>
            </div>
        </div>
    </div>
</div>
{% endblock %}

最後に認証後のdashboard画面dashboard/template/dashboard.html。といっても今回は空っぽ。

{% extends 'base.html' %}
ビューとルーティングを作る

accountsアプリ

  • radish/accounts/views.py

何かしらで認証されっぱなしの状態にならないように、logoutを最初に呼んで初期化してる。

import logging
from django.shortcuts import render_to_response, HttpResponseRedirect
from django.template import RequestContext
from django.contrib.auth import authenticate, login, logout

logger = logging.getLogger(__name__)


def login_view(request):

    #強制的にログアウト
    logout(request)
    username = password = ''

    login_failed = False

    if request.POST:
        username = request.POST['username'].replace(' ', '').lower()
        password = request.POST['password']
        user = authenticate(username=username, password=password)
        if user is not None:
            if user.is_active:
                login(request, user)
                return HttpResponseRedirect('/dashboard')
        else:
            login_failed = True

    return render_to_response('accounts/login.html',
                              {'login_failed': login_failed},
                              context_instance=RequestContext(request))

上で作ったビューをwebブラウザから/accounts/loginでアクセスできるよう設定する。

  • radish/accounts/urls.py
from django.conf.urls import url
from .views import login_view

urlpatterns = [
    url(r'^login/$', login_view, name='login'),
]

dashboardアプリ

  • radish/dashboard/views.py

@login_requiredをつけて、認証後のみアクセス可能なようにしている。

import logging

from django.shortcuts import render
from django.contrib.auth.decorators import login_required


@login_required
def index(request):
    return render(request, 'dashboard/index.html')
  • radish/dashboard/urls.py
from django.conf.urls import url
from .views import index

urlpatterns = [
    url(r'^$', index, name='dashboard'),
]
動作確認

ユーザを作成する。今回はスーパーユーザを造り、そのままそのアカウントでログインしてみる。

$ python manage.py createsuperuser
...
(対話的に作成)
...

動作確認として、開発サーバを起動$ python manage.py runserver、webブラウザからhttp://localhost:8000/にアクセスして、先ほど登録したスーパーユーザでログインし、NavbarにDashboard, Settingsというメニューが出ていることを確認する。

Djangoのフロー

DjangoフルスタックなWebフレームワークで、Ruby on RailsのようなDBマイグレーションができたり、管理GUIを簡単に作る機能があるなど、使えたら便利そう。

1) プロジェクトを作成する

$ django-admin startproject (プロジェクト名)

2) アプリケーションを作成する

$ python manage.py startpapp (アプリケーション名)

3) ビューを作成する

3)-1. (アプリケーション名)/views.pyを改修する
3)-2. (アプリケーション名)/urls.pyを改修する
3)-3. テンプレート(*.html)を作成する (js, cssは(プロジェクト名)/staticディレクトリ配下に入れる)

*テンプレート単体で確認できないのかな?

4) モデルを作成する

4)-1. (プロジェクト名)/(プロジェクト名)/settings.pyでデータベースを設定する
4)-2. (アプリケーション名)/models.pyを改修する
4)-3. (プロジェクト名)/(プロジェクト名)/settings.pyのINSTALLED_APPSを編集し、モデルを有効にする
4)-4. マイグレーションを実施する

$ python manage.py makemigrations (アプリケーション名)
$ python manage.py sqlmigrate (アプリケーション名) 0001  <= データベーススキーマを確認
$ python manage.py migrate

*ER図->DB--(リバース)-->モデル--(モデル修正)-->モデル'--(マイグレーション x n回)-->DB'の方がいきなりコードを書けないので、馴染める。

JacksonでLombokを使ったBeanにマッピングできない

同じ轍を踏まないようにメモ。

事象

JSONファイルから設定を読み込むことをしたく、Jacksonを使い、アクセッサーメソッドの記述を省力化しようとLombokを使った。そのとき下記のように記載するとアクセッサーメソッドがスネークケースになって(実際スネークケースになる設定というわけではなく、頭文字を大文字にして繋げる仕様で、"_"だからそれに対応できなかっただけのような気がする気がする...)、アンマーシャルすることができないエラーが発生する。

f:id:hermesian:20160207222514p:plain

import lombok.Getter;
import lombok.Setter;

public class Bean {

    @Getter
    @Setter
    private Parent1 _parent1;

    public class Parent1 {

        @Getter
        @Setter
        private String _child1;

        @Getter
        @Setter
        private String _child2;

        @Getter
        @Setter
        private String _child3;
    }
}
対策

属性の接頭辞には、"_"を使用しないこと。

f:id:hermesian:20160207222521p:plain

import lombok.Getter;
import lombok.Setter;

public class Bean {

    @Getter
    @Setter
    private Parent1 parent1;

    public class Parent1 {

        @Getter
        @Setter
        private String child1;

        @Getter
        @Setter
        private String child2;

        @Getter
        @Setter
        private String child3;
    }
}
バージョン

pom.xmlの内容は下記。

...以上、省略....
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.7.0</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.6</version>
        </dependency>
...以下、省略....

初段になりました

初めて審査なるものを受けました。 あいにくの雨。そして傘を忘れた...

審査は、術科試験と学科試験の2種。 ウェイトは不明だが、まれに学科で落ちることがあるとのことなので、術科にウェイトがあるような印象。

術科試験

一手座射が内容です。体配(執弓の姿勢、歩き方、坐しての回り方)が何よりも重要。 明らかに練習不足...。揖してからのモタつき、極め付けは射位を行き過ぎてしまいました。

学科試験

今年から学科の問題が公表されました(http://osaka-kyudo.jp/mondai_chiren_rengou.pdf)。 「A群、B群からそれぞれ1問、計2問を出題する。」を読んでいなかったため、「45分でこの量を書くのか...」と思い、キーワードを抑えることに集中していました。 終わった後、周りの方はほぼ15行びっしり記載されており、短すぎたかと焦りました(緊張すると震えてスラスラ書けない...)が、結果的には通ったようです。次は小論文などある程度の文量は書くトレーニングをし、そして硬筆の練習して臨みたいところ。

初心者弓道教室に参加して

初心者教室について

流山に越してから腰を据えて弓道を始めようと思い、まずは地域の弓道協会が主催する初心者教室に参加してみた。 計8回(5/30, 5/31, 6/6, 6/13, 6/14, 6/20, 6/21, 6/27)で先週がちょうど最終回だった。

  • 対象者は?

初心者でなくとも段を持っていない場合、様子をうかがえることから参加する方が良いと思う。 各地の道場における独自ルールもあると思うので。

課題

内省の意味を込めて、ここに記録しておく。

  • 足踏み
    • 左足の角度が開きすぎ
    • 幅が狭い
    • 胴が曲がっている(自分が正面であると思ったところから5cm後ろであった)
  • 弓構え
    • 手の内では指の「腹」でつかむ
  • 大三
    • 妻手は引かない
    • 肘を張る
  • 引分け
    • 左右に均等に引く(斜め後ろではなく)
  • 離れ
    • 射る瞬間に目をつぶることがある

その他

  • 弦を掛ける際は、順手
  • 矢番えの際は、気持ち前傾姿勢(仰け反って見えるときがある)

APIで取得したjsonが文字化けする

備忘録としてメモ。 やりたいことは、REST API提供されているデータを取得して、保存することです。

また使用しているpythonの環境は、以下。

 python --version
Python 3.4.3 :: Anaconda 2.2.0 (x86_64)

使用するデータは、e-StatのAPIから取得します。 APIを使用するに歳しては、まずユーザ登録をして、アプリケーションIDを発行しなくてはなりません。

www.e-stat.go.jp

提供されている機能としては5種類あります。 主に使いそうなものとしては、下記の2点になるかと思います。

  1. 使いたいデータの政府統計コードを使って、「統計表情報取得」機能から利用したい統計表IDを取得
  2. 「統計データ取得」機能からデータを取得

今回は、2点目の機能を利用。 平成22年国税調査 速報集計(0003033021)を例として、取得してみました。

#! /usr/bin/env python
#-*- coding: utf-8 -*-

import urllib.request, urllib.parse
import json, sys

def getEStatData():
    jsonUrl = "http://api.e-stat.go.jp/rest/2.0/app/json"
    apiKey = "(YOUR API KEY)"
    statId = "0003033021" # 平成22年国税調査 速報集計

    statsDataUrl = "%s/getStatsData?appId=%s&statsDataId=%s"
    url = (statsDataUrl % (jsonUrl, apiKey, statId))
    print(url)
    f = urllib.request.urlopen(url)
    jsonData = json.loads(f.read())
    print (jsonData)

    file = open('StatsData.json', 'w')
    json.dump(jsonData, file, sort_keys=True, indent=4)
    file.close()

if __name__ == '__main__':
    sys.exit(getEStatData())

urlib.request.urlopenがbyte型を返すことに注意(参考; http://docs.python.jp/3/library/urllib.request.html)

TypeError: the JSON object must be str, not 'bytes'

下記のようにutf-8にデコードすると日本語のままデータが取得できますが、このようにデコードした場合でもERROR_MSG":"\u6B63\u5E38\u306B\u7D42\u4E86\u3057\u307E\u3057\u305F\u3002"Unicodeエスケープされてしまう場合があったのですが、そんなときにはunicode-escapeを指定することで、回避していました。(正直、違いがわからない)。

    jsonData = json.loads(f.read().decode('utf-8'))
    print (jsonData)

一方で、出力したjsonファイルの方は、Unicodeエスケープされてしまいます。 これはjson.dumpsの引数であるensure_asciiがデフォルトでTrueになっており、入ってくるデータをエスケープする仕様になっていることに起因します。

従って、それをFalseにすることで、ファイルに書き出したときも日本語が保つことができます。

    file = open('StatsData.json', 'w')
    json.dump(jsonData, file, sort_keys=True, indent=4, ensure_ascii=False)
    file.close()

if __name__ == '__main__':
    sys.exit(getEStatData())

LeafletとCrossletを組み合わせたCrossLetで日本の人口統計データを表示する

CrossletというLeafletの地図表示上と、Crossfilterを連動させたJavascriptライブラリを用いて、各都道府県の国籍別に人口データを表示してみました。

ライブラリはLeafletがCloudMadeのAPIを使う仕様のままになっており、 今のLeafletのようにOpen Street Mapを使うようにライブラリの修正が必要ですが、 今回はそのまま利用しました。

github.com

ちなみにこのCrossletのことをRライブラリのrMapsではじめて知りました。 rMapsは、rChartsやSlidifyと同じ方で、Rのビジュアライゼーションの可能性を広げられてます。

データ

  • 日本topojsonデータ

D3.jsが流行ってからShapefileからTopojsonを作る解説が巷にいくつもでているので、割愛。 Topojson形式のデータを使用していますが、Geojsonもサポートされているそうです。

Crosslet also supports TopoJSON, a GeoJSON extension that allows to present geometry in a highly compact way.

人口統計データは、e-Statという政府統計データのポータルサイトからダウンロード致しました。項目は「外国人」にある41項目目です。そのままCSVをダウンロードするのではなく、[DB]から都道府県だけにデータをそぎ落としてからCSV形式でダウンロードしました。

その他にもデータにした修正 * 文字コードの修正 (Shift-JISからUTF-8) * ヘッダーの修正 * 文字列の数字を数値データ

"1234"みないなデータであれば、pandas.DataFrame.as_typeで変換できますが、"1,234"とカンマが入っていたために詰まった..。 データ少なかったから手で修正してしまったけど、課題として残しておく。

Crosslet

CSS

LeafletとCrossletのCSSを読み込みます。

<link rel="stylesheet" href="styles/crosslet-min.css" />
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css" />
    <style>
      html{
        height: 100%;
      }

      body{
        margin: 0px;
        padding: 0px;
        height: 100%;
      }

      #map{
        height: 100%;
      }
    </style>

Javascript

Backboneを採用しているとのこと。ほー。

<script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.2/underscore-min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/2.10.0/d3.v2.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.2/backbone-min.js"></script>
<script src="scripts/lib/crosslet.js"></script>

Crossletの描画設定

Crossletは、設定をJson形式で記載してCrossletのインスタンスを生成する際に引数で与えます。 このJsonの中身は以下のようになっています。

var config = {
  map : {
      (LeafletとオーバーレイさせるGeojsonまたはTopojsonの設定)
  },
  data : {
      (読み込むデータのうち、先に読み込んだGeojsonまたはTopojsonの各地域と結ぶための列名を指定)
  },
  dimensions : {
      (地図と関連させる棒チャートの設定。データの読み込む列やフォーマット、カラースケールを設定)
  },
  defaults: {
      (棒チャートのパネルの表示を設定)
  }
};

new crosslet.MapView($("#map"),config);

あとはhtmlのmap要素に表示されます。

  <div id="map"></div>
map

CloudMadeのAPIはもう利用できないので、leafletの設定はほっておきます。TopoJsonはgeo配下で設定しています。 name_fieldは表示名として使用されるもので、TopoJsonの中のフィールド名を指定します。id_fieldは後ほど読み込むデータと行を一致させるための一意になっているフィールド名Topojsonから選びます。 topo_objectはTopojsonの時に必須の項目で、Topojsonの中から"objects"のすぐ直下のフィールド名を拾います。

  map: {
    leaflet: {
      key: (CloudMade発行のAPI Key,
      styleId: 64657,
      attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="http://cloudmade.com">CloudMade</a>'
    },
    view: {
      center: [39, 135],
      zoom: 6
    },
    geo: {
      url: "data/crosslet/japan.topo.json",
      name_field: "name_local",
      id_field: "name",
      topo_object: "japan"
    }
  },
data

versionは特につかっていないようなので、データの列名で先ほど設定したid_fieldと一致させる列名を指定します。

data: {
    version: "1.0",
    id_field: "id"
  },
dimension

ほぼ同じ設定なので、一例のみ。japaneseとあるフィールド名はこの後のdefaultで指定するので一意に設定します。 titleは各パネルに表示されるタイトル、dataSetは読み込むデータファイル, fieldはそのうちこのパネルで読み込むデータ列の列名, さらに読み込むデータファイルの形式はデフォルトTSVですが、methodd3.csvとするとCSV形式を読むことができます。colorscale には、d3.scale.linear()を渡してカラースケールを設定することができます。最後のformatは、別に定義したvar inp = function() { return d3.format(",.0f") };を渡して、千の位にカンマを入れるフォーマットにしています。またshortも表示される表示データのフォーマットを指定するものです。

dimensions: {
    japanese: {
      title: "Japanese population",
      data: {
        dataSet: "data/crosslet/foreign_census.csv",
        field: "日本人",
        method: d3.csv,
        colorscale: d3.scale.linear().domain([0,5,20]).range(["green","yellow","red"]).interpolate(d3.cie.interpolateLab)
      },
      format:{
        short: inp,
      },
    },
  },
defalt

最後のdefaultは、パネルの並びとアクティブなパネルの設定を設定します。 opacityはパネルの透過度かとも思ったんですが、変えても変化がない...。 これはソースコード読まないとわからないですね。

  defaults: {
    opacity: 0.7,
    order: ["korean", "chinese", "philipino", "thai", "indonesian", "vietnamese", "english", "american", "brazilian", "peruvian", "others", "japanese"],
    active: "korean"
  },

消えた兵庫県

表示してみたら、兵庫が消えた\(^o^)/ というか静岡もnull !

f:id:hermesian:20150329200753p:plain

原因

Topojsonを見てみたら、Hyōgoとなっているoに長音記号がついてる...。 静岡もname_localがnullになっていたので修正して、無事表示されました。

f:id:hermesian:20150329200807p:plain