書類管理ウェブシステム構築(1): サーバサイド環境構築・LDAP ログイン
家にある書類たち,管理はめんどくさいし,参照するときに探したりするのは手間だし,最近 PDF 交付なども増えてるし,せっかくスキャナ付き複合機あるし,NAS もあるので,お手製書類管理ウェブシステムを作成します。
今回は第1回として django の開発環境の構築と LDAP 認証の対応までを記録として残しておきます。
フレームワークのインストール
今回は django を用いて構築します。
また,django rest framework を使うためインストールします。
合わせて便利そうなので django-filter, django-extensions, django-model-utils もインストールします。
$ pipenv --python 3.8
$ pipenv install django djangorestframework django-filter django-extensions werkzeug django-model-utils
project の作成
プロジェクトを作成します。
デフォルトのやり方だと,[プロジェクト名]/[プロジェクト名]
ディレクトリに設定ファイルが生成されわかりづらいため,下記のような手順でセットアップし [プロジェクト名]/config
ディレクトに設定ファイルが生成されるようにします。
$ mkdir docms
$ cd docms
$ pipenv run django-admin startproject config .
忘れる前に設定ファイル docms/config/settings.py
を変更します。
django-extensions を有効化します。
また,SECRET_KEY と DEBUG は環境変数などで適切に扱えるようにしましょう。
ローカライズ設定も忘れずに。
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
+ 'django_extensions',
]
...
- LANGUAGE_CODE = 'en-us'
+ LANGUAGE_CODE = 'ja-jp'
- TIME_ZONE = 'UTC'
+ TIME_ZONE = 'Asia/Tokyo'
linter/formatter/test の準備
python の linter, formatter とテストの際にカバレッジ計算するためのライブラリをインストールしましょう。
$ pipenv install --dev flake8 autopep8 coverage mypy pydocstyle
flake8 と coverage の設定ファイルを用意します。
tox.ini
:
[flake8]
exclude = .venv
[coverage:run]
omit = */tests/*,.venv/*
[coverage:html]
directory = cover
エディタの設定
今回は Visual Studio Code を使用します。
まずは,拡張の Python, Docker, Python Docstring Generator をインストールします。
次に設定ファイル .vscode/settings.json
を用意します:
{
"python.pythonPath": ".venv/bin/python3.8",
"python.linting.enabled": true,
"python.linting.lintOnSave": true,
"python.linting.pylintEnabled": false,
"python.linting.flake8Enabled": true,
"python.linting.flake8Args": [
"--max-complexity=10"
],
"python.formatting.provider": "autopep8",
"python.formatting.autopep8Args": [
"--aggressive", "--aggressive",
],
"autoDocstring.docstringFormat": "numpy",
}
追記
Pylance が話題になっていたので,追加で導入しました。
カスタム User モデルの作成
User は後々の拡張などに備え,django 標準の物を継承して作成したモデルを用いることが推奨されています。
AbstractBaseUser
を継承するパターンと AbstractUser
を継承するパターンがありますが,今回は難易度の比較的低い AbstractUser
を継承したクラスを用います。
まずはアプリを作成します:
$ pipenv shell
$ cd docms
$ ./manage.py startapp users
その後,各ファイルを用意します。
docms/users/models/user.py
:
import uuid
from django.contrib.auth.models import AbstractUser
from django.db import models
class User(AbstractUser):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
docms/users/models/__init__.py
:
from .user import User # noqa
docms/users/admin.py
:
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import User
admin.site.register(User, UserAdmin)
id の UUID 化は django-model-utils
を使う方法もありますが,今回は愚直に設定しました。
今回,モデルはディレクトリを作成し,その中で管理することとしたので models.py
を削除しましょう:
$ rm docms/users/models.py
その後,設定ファイル docms/config/settings.py
を書き換えます:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django_extensions',
+ 'users',
]
...
+ AUTH_USER_MODEL = 'users.User'
ここまできたらまずはマイグレーションファイルを作成します。
このマイグレーションファイルはコマンドで作成可能です:
$ pipenv shell
$ cd docms
$ ./manage.py makemigrations
すると自動で docms/users/migrations/0001_initial.py
にファイルが生成されるので,軽く目を通すとどういう働きをするファイルか理解できると思います。
ひとまずは簡単に動作を確認したいので,そのまま以下のコマンドを入力します:
$ pipenv shell
$ cd docms
$ ./manage.py migrate
するとデフォルトでは SQLite のファイルが生成されます。
(データベースの設定はそのうちちゃんとやります。)
LDAP 認証の実装
別で LDAP サーバがある環境なので,アカウント認証は LDAP サーバと連携させたいです。
そこで etianen/django-python3-ldap: Django LDAP user authentication backend for Python 3. を用いて,LDAP の情報でログインを行えるようにします。
$ pipenv install django-python3-ldap
インストールができたら settings.py
の INSTALLED_APPS
に 'django_python3_ldap'
を追加,AUTHENTICATION_BACKENDS
に ("django_python3_ldap.auth.LDAPBackend",)
を設定します。
また,settings.py
にその他必要な設定を書き込みます。
実際の settings.py
を下に示します(LDAP 関連の設定の一部は環境変数を使用するように設定していますがそのまま掲載します):
...
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
+ 'django_python3_ldap',
'users',
]
...
+ AUTHENTICATION_BACKENDS = ("django_python3_ldap.auth.LDAPBackend",)
...
+ LDAP_AUTH_URL = os.getenv('LDAP_AUTH_URL')
+ LDAP_AUTH_USE_TLS = True\
+ if os.getenv('LDAP_AUTH_USE_TLS')\
+ and os.getenv('LDAP_AUTH_USE_TLS') in ['true', 'True']\
+ else False
+ LDAP_AUTH_SEARCH_BASE = os.getenv('LDAP_AUTH_SEARCH_BASE')
+ LDAP_AUTH_OBJECT_CLASS = os.getenv('LDAP_AUTH_OBJECT_CLASS')
+
+ LDAP_AUTH_USER_FIELDS = {
+ "username": "cn",
+ "first_name": "givenName",
+ "last_name": "sn",
+ "email": "mail",
+ }
LDAP の設定の詳しい内容やここにはない設定は etianen/django-python3-ldap > Available settings を確認してください。
LDAP アカウントの管理者ユーザ化
通常であれば,python manage.py createsuperuser
を用いて管理者ユーザ(スーパユーザ)を作成するところですが,今回は LDAP 認証を用いてログインを行い,その username に基づいて管理者ユーザかどうかを判別できるようにします。
と言ってもやり方は簡単です。
以下のコマンドを実行してください (<username>
は管理者ユーザの username を指定する):
$ pipenv shell
$ cd docms
$ ./manage.py ldap_sync_users
$ ./manage.py ldap_promote <username>
実行に成功したら,LDAP サーバへの接続が成功しており,指定ユーザを管理者ユーザに設定完了しています。
下のコマンドでサーバを起動したのち,http://127.0.0.1:8000/admin/login/
にアクセスをして上で指定したユーザでログインがうまくいくか確認しましょう。
$ pipenv shell
$ cd docms
$ ./manage.py runserver
参考
- [Django] プロジェクト構成のベストプラクティスを探る - 1.設定ディレクトリの名前を変更する - Qiita
- Deployment checklist | Django documentation | Django
- Coverage.pyでDjangoアプリケーションのカバレッジを計測する - Qiita
- Configuration reference — Coverage.py 5.1 documentation
- Pipenvでnpm-scriptsみたいにPipfileへコマンドを書く - Qiita
- Customizing authentication in Django | Django documentation | Django
- django-uuidfieldを主キーにして少し困った話 - Qiita
- etianen/django-python3-ldap: Django LDAP user authentication backend for Python 3.
Discussion