Yura YuLife

ITエンジニアの覚え書き。

AtomでDjangoのテンプレート編集時にEmmetを有効化

AtomのEmmetは、デフォルトでHTML, CSS, Sass/SCSS, LESSの編集時のみ、タブキーで補完ができる設定になっています。

そのため、django-templatesのように、HTML以外のシンタックスでEmmetを利用する場合には別途設定が必要です。

インストール済みパッケージ

HTML (Django)の編集時にEmmetのタブ補完を有効化

  • AtomのメニューのEdit > Open Your Keymapを選択
  • keymap.csonというファイルが開くので、以下の内容を追記
'atom-text-editor[data-grammar="text html django"]:not([mini])':
    'tab': 'emmet:expand-abbreviation-with-tab'

これで、Djangoのテンプレート編集時にもEmmetのタブ補完が有効になります。

参考URL

Djangoの環境構築(Ubuntu Server, Apache, PostgreSQL)

以下の環境でDjangoを動作させるまでの手順をまとめました。

Django 1.7, PostgreSQL 9.Xでも同様の手順で構築が可能です。

パッケージのインストール

Python

$ sudo apt-get install python-dev

Apache2, mod-wsgi

$ sudo apt-get install apache2 apache2-dev libapache2-mod-wsgi

PostgreSQL

$ sudo apt-get install postgresql-9.3 postgresql-server-dev-9.3

Virtualenv

$ sudo apt-get install python-virtualenv

動作環境の構築

構築する環境

以下のような設定でデプロイを行うとする。

  • Djangoのプロジェクト名: hoge
  • Djangoプロジェクトのデプロイ先パス: /var/www/django/hoge/
  • DjangoのVirtualenvのインストール先パス: /var/www/django/venv/
  • Djangoプロジェクトのstaticファイルのパス: /var/www/static/
  • 管理ユーザ名: username
  • Djangoプロジェクトが利用するPostgreSQLのデータベース, ロール, パスワード:django_db, django_role, django_pass

Djangoのプロジェクトのファイルをコピー

$ sudo mkdir /var/www/django/
$ sudo cp -r ~/hoge /var/www/django/

Virtualenvを作成

$ cd /var/www/django/
$ sudo virtualenv venv
$ sudo chown -R username:www-data /var/www/django/

Virtualenvにpythonのライブラリのインストール

$ source /var/www/django/venv/bin/activate
(venv) $ pip install Django psycopg2 pytz
(venv) $ deactivate

PostgreSQLデータベースの作成

$ su -
# su postgres
$ psql
# CREATE ROLE django_role LOGIN PASSWORD 'django_pass';
# CREATE DATABASE django_db OWNER django_role;
# \q
$ exit
# exit

初期データの設定

DBのマイグレーション

$ cd /var/www/django/hoge/
$ source /var/www/django/venv/bin/activate
(venv) $ ./manage.py makemigrations
(venv) $ ./manage.py migrate
(venv) $ deactivate

staticファイルのコピー

$ cd /var/www/
$ sudo mkdir static
$ sudo chown -R username:www-data static
$ cd /var/www/django/hoge/
$ source /var/www/django/venv/bin/activate
(venv) $ ./manage.py collectstatic
(venv) $ deactivate

Djangoプロジェクトのスーパーユーザの作成 (管理サイトを利用する場合)

$ cd /var/www/django/hoge/
$ source /var/www/django/venv/bin/activate
(venv) $ ./manage.py createsuperuser
(venv) $ deactivate

Webサーバの設定

Apache2の設定を作成

/etc/apache2/sites-available/django.conf

<VirtualHost *:80>

ServerName www.example.com
ServerAdmin root@localhost

Alias /static/ /var/www/static/

<Directory /var/www/static>
# ディレクトリの中身を非表示にする
Options -Indexes +FollowSymLinks
Order deny,allow
Allow from all
</Directory>

# WSGIの設定
WSGIDaemonProcess django_wsgi python-path=/var/www/django/hoge:/var/www/django/venv/lib/python2.7/site-packages
WSGIProcessGroup django_wsgi
WSGIScriptAlias / /var/www/django/hoge/hoge/wsgi.py

<Directory /var/www/django/hoge/hoge>
  <Files wsgi.py>
    <IfVersion < 2.3 >
      Order allow,deny
      Allow from all
    </IfVersion>
    <IfVersion >= 2.3>
      Require all granted
    </IfVersion>
  </Files>
</Directory>

# ログ出力の設定
ErrorLog /var/log/apache2/django-error.log
LogLevel warn
CustomLog /var/log/apache2/django-access.log combined
</VirtualHost>

Apache2の設定を変更

$ sudo a2enmod ssl
$ sudo a2enmod wsgi
$ sudo a2dissite 000-default.conf
$ sudo a2ensite django.conf

Apache2の起動

$ sudo service apache2 start

動作確認

ブラウザからアクセスして、ページが表示されれば成功。

Djangoでフォーム内でクリックされたボタンによって異なる処理を行う

タイトルの通り、同一フォーム内でクリックしたボタンによって異なる処理を行いたい場合は以下のように書きます。

hoge.html

<form action="{% url 'hoge.views.some_view' %}" method="post">
  {% csrf_token %}
  <input type="text" name="hoge" value="">
  ...
  <input type="submit" name="button_1" value="ボタン1"> 
  <input type="submit" name="button_2" value="ボタン2"> 
</form>

views.py

def some_view(request):
    if request.method == 'POST':
        if 'button_1' in request.POST:
            # ボタン1がクリックされた場合の処理
            hoge1()
        elif 'button_2' in request.POST:
            # ボタン2がクリックされた場合の処理
            hoge2()

Djangoで特定のページのみBasic認証をかける

やり方は、以下のページの通りです。

djangosnippets: view by view basic authentication decorator

スニペットの保存

まず、上記サイトのスニペットをコピー&ペーストして、プロジェクト内に保存します。

basic_auth_view.py

import base64

from django.http import HttpResponse
from django.contrib.auth import authenticate, login

#############################################################################
#
def view_or_basicauth(view, request, test_func, realm = "", *args, **kwargs):

(中略)

    def view_decorator(func):
        def wrapper(request, *args, **kwargs):
            return view_or_basicauth(func, request,
                                     lambda u: u.has_perm(perm),
                                     realm, *args, **kwargs)
        return wrapper
    return view_decorator

ビュー内で呼び出し

上記手順で保存したファイルから利用する関数をimportし、ビューのデコレータとして記述します。

views.py

from basic_auth_view import logged_in_or_basicauth

# ログインもしくはBasic認証で閲覧できるビュー
@logged_in_or_basicauth()
def some_view(request):
   ...
   return render( ... )

Apache2の設定に追記

WSGIモジュールでBasic認証を利用可能にするため、Apache2のサイトのconfファイルに以下の内容を追記します。

WSGIPassAuthorization On

実際に試してみる

ブラウザからBasic認証を追加したURLへアクセスすると、未ログインの場合はBasic認証のダイアログが表示され、ログイン済みの場合はページが表示されます。

f:id:yurayur:20150331233357p:plain

DjangoのQuerySetでランダムに要素を取得

例えば、SomeModelというモデルクラスのインスタンスを10個取得する場合。

random_query_set = SomeModel.objects.order_by('?')[:10]

QuerySet API reference | Django documentation | Django

ただし、リファレンスによるとバックエンドで利用しているDBによっては、order_by('?')は非常に遅くなる場合があるので利用には注意が必要です、とのこと。

下記サイトの情報によると、MySQLではORDER BY ?は非常に計算コストがかかるらしいです。

snipplr.com