偏った言語信者の垂れ流し

2015-07-21

[][]DjangoテンプレートのstaticタグとSTATIC_URLコンテキスト変数の使い分け

Djangoテンプレートで静的ファイルのパス指定時にdjango.contrib.staticfilesのstaticタグとSTATIC_URLのどちらを使うべきか、という質問があったので、少し調べました。この記事はDjango 1.8のドキュメントとコードを参考にしています。

結論としてはstaticタグを使ったほうが、テンプレートの再利用性は高いです。

STATIC_URLコンテキスト変数

STATIC_URLコンテキスト変数は、Djangoの設定ファイル(settings)に指定したSTATIC_URLがそのまま格納されています。

django/template/context_processors.py#L74

また、コンテキスト変数の参照を避けるのであれば、get_static_prefixタグを使ってSTATIC_URLの値を取得することもできます。

staticタグ

staticタグは、デフォルトテンプレートタグではないので、使用する際にはloadタグによる指定が必要です。

{% load staticfiles %}

staticタグには、コンテキスト変数文字列を指定できます。

また、staticタグの場合、STATIC_URLと直接結合するのではなく、ストレージクラスurlメソッドを呼び出して、その結果が出力として使われます。

ストレージ側にURLの生成を任せる場合は、staticタグを使う必要があります。

django/contrib/staticfiles/templatetags/staticfiles.py#L9

settings.STATICFILES_STORAGEでストレージを変更することを想定するなら、STATIC_URLよりもstaticタグを使ったほうが良いようです。

参考

2015-07-05

[][]PostgreSQLでウィンドウ関数rankを試す

SQLのウィンドウ関数を使うと、グループ化しつつ、グループ内でランキングを作成するのが簡単と聞いていたので、PostgreSQLで試していた。

PostgreSQLのバージョンは、9.4.4

対象のデータ

ウィンドウ関数を試すにあたって、商品、カテゴリ、売上という3つのテーブルを作成し、データを投入した。

ER

A5:SQL Mk-2を使って作成。

f:id:nullpobug:20150705151518p:image

DDL

ER図から出力したDDLを使う。

-- 売上
drop table if exists sales cascade;

create table sales (
  id serial not null
  , item_id integer not null
  , category_id integer not null
  , price integer not null
  , constraint sales_PKC primary key (id)
) ;

-- 商品
drop table if exists item cascade;

create table item (
  id serial not null
  , name character varying(50) not null
  , price integer not null
  , category_id integer not null
  , constraint item_PKC primary key (id)
) ;

-- カテゴリ
drop table if exists category cascade;

create table category (
  id serial
  , name character varying(50) not null
  , constraint category_PKC primary key (id)
) ;

データの投入

各テーブルに、集計できる最低限ぐらいのデータを入れておいた。

insert into category(id,name) values (1,'野菜');
insert into category(id,name) values (2,'果物');
insert into item(id,name,price,category_id) values (1,'じゃがいも',30,1);
insert into item(id,name,price,category_id) values (2,'にんじん',80,1);
insert into item(id,name,price,category_id) values (3,'たまねぎ',50,1);
insert into item(id,name,price,category_id) values (4,'りんご',70,2);
insert into item(id,name,price,category_id) values (5,'みかん',30,2);
insert into sales(id,item_id,category_id,price) values (1,1,1,30);
insert into sales(id,item_id,category_id,price) values (2,1,1,30);
insert into sales(id,item_id,category_id,price) values (3,1,1,30);
insert into sales(id,item_id,category_id,price) values (4,1,1,30);
insert into sales(id,item_id,category_id,price) values (5,2,1,80);
insert into sales(id,item_id,category_id,price) values (6,2,1,80);
insert into sales(id,item_id,category_id,price) values (7,3,1,50);
insert into sales(id,item_id,category_id,price) values (8,4,2,70);
insert into sales(id,item_id,category_id,price) values (9,4,2,70);
insert into sales(id,item_id,category_id,price) values (10,5,2,30);
insert into sales(id,item_id,category_id,price) values (11,5,2,30);
insert into sales(id,item_id,category_id,price) values (12,5,2,30);

ウィンドウ関数のrankを使ったクエリ

集計結果にランクをつけるクエリを試した。

with sales_report as (
  select
    I.name
    , I.category_id
    , count(I.id) cnt
    , sum(I.price) price 
  from
    sales S 
  inner join item I 
    on S.item_id = I.id 
  inner join category C 
    on S.category_id = C.id 
  group by
    I.id
),
item_rank as ( 
  select
    sales_report.*
    , rank() over (partition by sales_report.category_id order by cnt) count_rank
    , rank() over (partition by sales_report.category_id order by price) price_rank 
  from
    sales_report
) 
select
  * 
from
  item_rank 
where
  count_rank < 3;

1つ目のsales_reportは、売上テーブルのデータを商品IDでグループ化して、売上の合計金額と個数を出す。

2つ目のitem_rankは、rank関数を使って個数と合計金額をカテゴリID毎にランク付けする。

3つ目は、個数のランクが3未満のものだけに絞り込む。

実行結果

f:id:nullpobug:20150705151803p:image

参考

2015-06-26

[]MikroTik RB750GLを購入

タイトルの通り、MikroTikのルーター (RouterBOARD)、RB750GLを購入しました。

RouterBoard.com : RB750GL

社内で希望者を集めて共同でAmazon.comから購入。海外発送で送料込み、1台あたり7400円ぐらいでした。

電源アダプタのプラグがCタイプなんですが、日本のコンセントに合うAタイプに変換するプラグも付属していました。

f:id:nullpobug:20150626230258p:image

f:id:nullpobug:20150626225726p:image

初期設定では、ポート1にインターネット側のLANケーブル、ポート2〜5に利用するコンピュータ側のLANケーブルをつなぐと、DHCPでアドレスが割り当てられてすぐに使える状態でした。

パッケージの背面に説明があります。

f:id:nullpobug:20150626230333p:image

デフォルトIPアドレスは 192.168.88.1 となっていました。

家のルーターハングアップすることが増えてたので、取り替えてしばらく使ってみようと思います。

参考

RouterBOARD はし?めの一歩

2015-06-24

[][]Django 1.8で追加されたSecurityMiddlewareについて

Django1.8で増えた機能でSecurityMiddlewareというものがあります。

何ができるのか把握しておきたかったので調べていました。

django.middleware.security.SecurityMiddleware

コードはこのあたり。

django/security.py at stable/1.8.x ? django/django ? GitHub

以下の内容は、Django1.8のドキュメントとコードを元に記述しています。

概要

SecurityMiddlewareは、Djangoアプリケーションへのリクエスト、レスポンスに対していくつかのセキュリティ強化を施します。

具体的には以下のような機能があります。

各機能は独立して有効、無効を設定できるようになっています。

HTTP Strict Transport Securityヘッダの付与

settings.SECURE_HSTS_SECONDSに秒数を設定すると、リクエストがHTTPSの場合に「strict-transport-security」ヘッダがレスポンスに付与されます。この際、max-ageはSECURE_HSTS_SECONDSの値になります。

settings.SECURE_HSTS_INCLUDE_SUBDOMAINSにTrueを設定すると、ヘッダの最後に「includeSubDomains」を追加で付与します。

X-Content-Type-Options: nosniff ヘッダの付与

settings.SECURE_CONTENT_TYPE_NOSNIFFにTrueを設定すると、「x-content-type-options: nosniff」ヘッダがレスポンスに付与されます。

X-XSS-Protection: 1; mode=block ヘッダの付与

settings.SECURE_BROWSER_XSS_FILTERにTrueを設定すると、「x-xss-protection: 1; mode=block」ヘッダがレスポンスに付与されます。

HTTPSスキームURLへのリダイレクト機能

settings.SECURE_SSL_REDIRECTにTrueを設定すると、HTTPDjangoアプリケーションにアクセスした際に、httpsで始まるURLリダイレクトするようにレスポンスを返します。

この際、ホスト名を変更したい場合はsettings.SECURE_SSL_HOSTにホスト名を指定できます。

また、特定のパスにアクセスした場合にリダイレクトさせたくない場合は、settings.SECURE_REDIRECT_EXEMPTに正規表現で除外するパターンを指定できます。

参考

2015-06-14

[]オープンソースカンファレンス2015 Hokkaidoに参加しました

タイトルの通り、オープンソースカンファレンス2015 Hokkaidoに参加してきました。

オープンソースカンファレンス2015 Hokkaido - オープンソースの文化祭!

LTでDjangoの紹介をしました。資料はSlideshareに置いてます。

Djangoフレームワークの紹介 OSC2015北海道