国土数値情報 行政区域データをGeoDjangoに取り込み
上記から行政区画データをダウンロードし、GeoDjangoから扱えるようにするための手順。
postgisはインストール済みとする。
地図情報のダウンロード
"全国"をクリックし最新の"N03-20150101_GML.zip"をダウンロード。
sqlファイル作成
上記を参考にsqlファイルを作成
shp2pgsql -s 4612 -D -i -I -W cp932 ~/Desktop/N03-20150101_GML/N03-15_150101.shp gisdata > ~/Desktop/gisdata.sql
参考サイトではJPGISからシェープファイルに変換する手順が必要とあるが、ダウンロードしたファイルに含まれていたのでそれを使用した。
既存のデータベースにデータを投入
psql postgres -f ~/Desktop/gisdata.sql
modelを定義
from django.contrib.gis.db import models class GisData(models.Model): gid = models.IntegerField(primary_key=True) n03_001 = models.CharField(max_length=10) n03_002 = models.CharField(max_length=20) n03_003 = models.CharField(max_length=20) n03_004 = models.CharField(max_length=20) n03_007 = models.CharField(max_length=5) geom = models.MultiPolygonField(spatial_index=True, srid=4612) objects = models.GeoManager() class Meta: db_table = 'gisdata' def __str__ (self): params = { 'gid': self.gid, 'n03_001': self.n03_001, 'n03_002': self.n03_002, 'n03_003': self.n03_003, 'n03_004': self.n03_004, 'n03_007': self.n03_007, } return '<GisData({gid}) n03_001:{n03_001} n03_002:{n03_002} n03_003:{n03_003} n03_004:{n03_004} n03_007:{n03_007}>'.format(**params)
使用方法
>>> from django.contrib.gis.geos import Point >>> from gisdata.models import GisData >>> point = Point(139.699578, 35.659531) # 渋谷駅周辺の座標 >>> r = GisData.objects.filter(geom__contains=point) >>> print(r[0]) <GisData(32097) n03_001:東京都 n03_002:None n03_003:渋谷区 n03_004:None n03_007:13113>
上記の感じで取得する。
あまりドキュメントを読まずにやったので、何か間違いがあるかも。
Cocos2d-JsでCocoaPodsを使用する
CocoaPodsのインストールは済ませたものとする
podの初期化
frameworks/runtime-src/proj.ios_mac/ pod init
Podfileの編集
今回はParseをインストールします。
vi Podfile
# Uncomment this line to define a global platform for your project # platform :ios, '6.0' target 'Cocos2dJsBase iOS' do pod 'Parse' end target 'Cocos2dJsBase Mac' do end
pod installを実行
$ pod install Analyzing dependencies CocoaPods 0.38.0.beta.2 is available. To update use: `gem install cocoapods --pre` [!] This is a test version we'd love you to try. For more information see http://blog.cocoapods.org and the CHANGELOG for this version http://git.io/BaH8pQ. Downloading dependencies Installing Bolts (1.2.0) Installing Parse (1.7.5) Generating Pods project Integrating client project [!] Please close any current Xcode sessions and use `Cocos2dJsBase.xcworkspace` for this project from now on. [!] The platform of the target `Cocos2dJsBase iOS` (iOS 5.0) may not be compatible with `Parse (1.7.5)` which has a minimum requirement of iOS 6.0. [!] The `Cocos2dJsBase iOS [Debug]` target overrides the `HEADER_SEARCH_PATHS` build setting defined in `Pods/Target Support Files/Pods-Cocos2dJsBase iOS/Pods-Cocos2dJsBase iOS.debug.xcconfig'. This can lead to problems with the CocoaPods installation - Use the `$(inherited)` flag, or - Remove the build settings from the target. [!] The `Cocos2dJsBase iOS [Debug]` target overrides the `LIBRARY_SEARCH_PATHS` build setting defined in `Pods/Target Support Files/Pods-Cocos2dJsBase iOS/Pods-Cocos2dJsBase iOS.debug.xcconfig'. This can lead to problems with the CocoaPods installation - Use the `$(inherited)` flag, or - Remove the build settings from the target. [!] The `Cocos2dJsBase iOS [Debug]` target overrides the `OTHER_LDFLAGS` build setting defined in `Pods/Target Support Files/Pods-Cocos2dJsBase iOS/Pods-Cocos2dJsBase iOS.debug.xcconfig'. This can lead to problems with the CocoaPods installation - Use the `$(inherited)` flag, or - Remove the build settings from the target. [!] The `Cocos2dJsBase iOS [Release]` target overrides the `HEADER_SEARCH_PATHS` build setting defined in `Pods/Target Support Files/Pods-Cocos2dJsBase iOS/Pods-Cocos2dJsBase iOS.release.xcconfig'. This can lead to problems with the CocoaPods installation - Use the `$(inherited)` flag, or - Remove the build settings from the target. [!] The `Cocos2dJsBase iOS [Release]` target overrides the `LIBRARY_SEARCH_PATHS` build setting defined in `Pods/Target Support Files/Pods-Cocos2dJsBase iOS/Pods-Cocos2dJsBase iOS.release.xcconfig'. This can lead to problems with the CocoaPods installation - Use the `$(inherited)` flag, or - Remove the build settings from the target. [!] The `Cocos2dJsBase iOS [Release]` target overrides the `OTHER_LDFLAGS` build setting defined in `Pods/Target Support Files/Pods-Cocos2dJsBase iOS/Pods-Cocos2dJsBase iOS.release.xcconfig'. This can lead to problems with the CocoaPods installation - Use the `$(inherited)` flag, or - Remove the build settings from the target.
エラーが出ているが次の項で修正する。
xcode起動
カレントディレクトリに Cocos2dJsBase.xcworkspace が作成されているので、こちらを使用してxcodeを起動
Build Settingsで
Header Search Paths
Library Search Paths
Other Linker Flags
に$(inherited)を追加
再度pod install
補足
Cocos2dJsBase.xcworkspaceに GameController.framework を手動で追加しないと動かないことがある?
fluxibleのサンプル(チャット)を読む
やること
Fluxible | A Pluggable Container for Isomorphic Flux Applications
というものがある。
今流行りのreact.jsを乗せたfluxアーキテクチャの実装の中では、割とオススメされているっぽいものだ。
これの習得をせまられる状況になったのだが、はっきり言ってチンプンカンプンである。そもそもnode自体の理解もおぼつかないのに、こんなこと人間にはできません。
とはいえ、下記のサンプル(chatの方)を読んで気合いで理解を進めた話。 github.com (commit:967b623e9411df46383e0ebe0adedec48e57d511)
app.js
flux-examples/app.js at master · yahoo/flux-examples · GitHub
var app = new Fluxible({ component: require('./components/ChatApp.jsx') });
まずはここから。
これがアプリケーションそのもので、これに対していろいろ設定を加えて行ってるっぽい。
引数のcomponentは
「Stores your top level React component for access using getComponent()
」
ってソースには書いてあるんだけど、だとしたら"components/Html.jsx"がトップレベルなんじゃないの?
分からないので飛ばします。
app.registerStore(require('./stores/RouteStore')); app.registerStore(require('./stores/MessageStore')); app.registerStore(require('./stores/ThreadStore')); app.registerStore(require('./stores/UnreadThreadStore'));
ここでは、データを溜め込むためのStoreをアプリケーション登録している。
server.js
flux-examples/server.js at master · yahoo/flux-examples · GitHub
サーバサイドでブラウザからのアクセスを待ち受ける為、最初に動くコードである。
require('babel/register')
このアプリに限ったことではないが、コードをES6で記述できるようにするものらしい。
var server = express();
pythonにおけるflask、rubyにおけるsinatra的なやつである。
// Get access to the fetchr plugin instance var fetchrPlugin = app.getPlugin('FetchrPlugin'); // Register our messages REST service fetchrPlugin.registerService(require('./services/message')); // Set up the fetchr middleware server.use(fetchrPlugin.getXhrPath(), fetchrPlugin.getMiddleware());
これはブラウザからサーバのコードを叩きたい時に、簡単に叩く為の入り口を設定してあげる機能と理解した。
以下のように書くと、サーバ側の処理を以下の様に呼び出せるようになる。
context.service.somefunc('message', message, {} ...
var context = app.createContext({ req: req, // The fetchr plugin depends on this xhrContext: { _csrf: req.csrfToken() // Make sure all XHR requests have the CSRF token } })
これがリクエストに紐づくコンテキスト。プラグインなんかを使うとこいつに対して便利なメソッドが生えるとか、生えないとか。
debug('Executing showChat action'); context.executeAction(navigateAction, { url: req.url, type: 'pageload' }, function (err) {
ここでアクションを実行し、結果的に必要な情報をStoreに登録している。
debug('Exposing context state'); var exposed = 'window.App=' + serialize(app.dehydrate(context)) + ';'; debug('Rendering Application component into html'); var html = React.renderToStaticMarkup(HtmlComponent({ state: exposed, markup: React.renderToString(context.createElement()) })); debug('Sending markup'); res.send(html);
exposedの中身をconsole.log gist.github.com contextに紐づくデータがjson形式でシリアライズされている様だ。
スレッド一覧やチャットの発言のデータも含まれる。htmlの中身をconsole.log gist.github.com exposedの内容を含むhtml全体が入っている。
data-reactid=".1dbtrevj3ls.0.1" みたいなのが、タグの属性に入ってるのがミソなんだろう、きっと。
client.js
flux-examples/client.js at master · yahoo/flux-examples · GitHub
こちらは、上記のサーバにアクセスしたのち、ブラウザ側で最初に実行されるコード。
bootstrapDebug('rehydrating app'); app.rehydrate(dehydratedState, function (err, context) {
dehydratedStateはサーバ側で格納されていたexposedの事である、app.rehydrateする事でcontextに復元を行っている。
var mountNode = document.getElementById('app'); bootstrapDebug('React Rendering'); React.render(context.createElement(), mountNode, function () { bootstrapDebug('React Rendered'); });
mountNodeっていうのが、app.jsで指定していた'./components/ChatApp.jsx'の中身になっているっぽい。
context.createElement()
というのは、「React.createElement」メソッドの結果が返るみたい。
nginxで自己認証証明書(おれおれ証明書)を設定
証明書の作成
秘密鍵を作成
# openssl genrsa -des3 -out server.key 2048 Generating RSA private key, 2048 bit long modulus .........................+++ .......................................+++ e is 65537 (0x10001) Enter pass phrase for server.key: Verifying - Enter pass phrase for server.key:
パスフレーズは後で外すので適当に
証明書署名要求を作成
# openssl req -new -key server.key -out server.csr Enter pass phrase for server.key: You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:JP State or Province Name (full name) [Some-State]:Tokyo Locality Name (eg, city) []:Shinjyuku Organization Name (eg, company) [Internet Widgits Pty Ltd]:xxx .inc Organizational Unit Name (eg, section) []: Common Name (e.g. server FQDN or YOUR name) []:xxx.com Email Address []:xxx@gmail.com Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []:
Common Nameとhost名を一致させる事、curlでテストする際に以下のエラーが出てしまいます。
ただ、他の環境だと平気かもしれないです。
curl: (51) SSL: certificate subject name 'xxx.com' does not match target host name 'yyy.com'
秘密鍵のパスフレーズを外す
openssl rsa -in server.key -out server.key
証明書を作成
openssl x509 -req -days 36500 -in server.csr -signkey server.key -out server.crt
nginx設定
serverに以下を追加
listen 443 ssl; ssl_certificate /path/to/server.crt; ssl_certificate_key /path/to/server.key;
curlで確認
適当なマシンにserver.crtを転送し
curl --cacert ./server.crt https://xxx.com
mysql(MYISAM)でGeoDjango
djangoで位置情報を使うためにはGeoDjangoという仕組みを使うと良いらしい。
GeoDjango | Django documentation | Django
この機能をフルで使う為にはデータベースをPostgreSQLにしなければならないのだが、簡単な機能であればmysqlでも大丈夫。
やり方
settings.py
INSTALLED_APPSに'django.contrib.gis'を追加する
INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'django.contrib.gis', )
DATABASES設定のENGINEを'django.contrib.gis.db.backends.mysql'に変更。
※'django.db.backends.mysql'では無いので注意
OPTIONSの部分でストレージエンジンをMYISAMに変更。
mysql5.6の時点ではMYISAMでないとGEOMETRY型(BLOB型)の列にスペシャルインデックスを貼る事ができない。
※innodbでは貼れない
DATABASES = { 'default': { 'ENGINE': 'django.contrib.gis.db.backends.mysql', 'NAME': 'dbname', 'USER': 'root', 'PASSWORD': '', 'HOST': '127.0.0.1', 'PORT': '', 'OPTIONS': { "init_command": "SET storage_engine=MYISAM", } } }
models.py
モデルの作成例。
ポイントは継承先とマネージャをデフォルトのものから変更する事。
from django.contrib.gis.db import models # Create your models here. class GeoDataLog(models.Model): latlng = models.GeometryField(spatial_index=True) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) objects = models.GeoManager()
使い方
insert
point = Point(float(lat), float(lng)) GeoDataLog.objects.create(latlng=point)
select
普通にマネージャインスタンスからクエリセットを作って、とか出来なくはないが、 位置情報を使った複雑なクエリを発行したいなら、生のsqlで取るのが良さそう。
下記は指定の位置から緯度経度+-{latlng_range}内の短形領域内で指定の位置から近いデータを抽出する為のサンプル
※SQLインジェクションには十分注意して下さい!
sql = """ SELECT id AS id, GLength( GeomFromText( CONCAT( 'LineString({lat} {lng},', X(latlng), ' ', Y(latlng), ')' ) ) ) AS length_km, X(latlng) AS lat, Y(latlng) AS lng FROM geodata_geodatalog WHERE MBRContains( GeomFromText( Concat( 'LineString(', {lat} + {latlng_range}, ' ', {lng} + {latlng_range}, ',', {lat} - {latlng_range}, ' ', {lng} - {latlng_range}, ')' ) ), latlng ) HAVING length_km < {length_limit_km} ORDER BY length_km """.format( lat=lat, lng=lng, latlng_range=latlng_range, length_limit_km=length_limit_km ) cursor = connection.cursor() cursor.execute(sql) cursor.fetchall()