【Django】ワンライナーでスーパーユーザーを作成する方法
Django Adminのスーパーユーザーをワンライナーで作成する方法を紹介します。
Django Adminのスーパーユーザーの作成は本来、createsuperuser コマンドで作成できますが、インタラクティブ(対話的)に実行されます。
$ python manage.py createsuperuser Username (leave blank to use 'root'): admin Email address: admin@example.com Password: Password (again): Superuser created successfully.
命令的に実行する場合はこれでもいいのですが、宣言的に実行したいケースがあります。
例えば、Docker Composeによる開発環境構築で、環境を立ち上げるたびにスーパーユーザーを作成するのは手間ですしスマートではありません。
環境を立ち上げるときにスーパーユーザーも作成されるのが理想です。
宣言的に実行するケースではパスワードを設定できないのが現在のDjangoの仕様です。パスワードを設定しないままスーパーユーザーを作成することも可能ですが、パスワードを設定するまでログインはできません。
そのためワンライナーで実行できるようにするためには createsuperuser コマンドを --password
のようなオプションでパスワードを指定できるようにカスタマイズしてあげる必要があります。
management/commands/
配下に custom_createsuperuser.py
のようなファイルを作成します。
from django.contrib.auth.management.commands import createsuperuser from django.core.management import CommandError class Command(createsuperuser.Command): help = 'Create a superuser with a password non-interactively' def add_arguments(self, parser): super(Command, self).add_arguments(parser) parser.add_argument( '--password', dest='password', default=None, help='Specifies the password for the superuser.', ) def handle(self, *args, **options): options.setdefault('interactive', False) username = options.get('username') email = options.get('email') password = options.get('password') database = options.get('database') if not (username and email and password): raise CommandError('--username, --email and --password are required options') user_data = { 'username': username 'email': email, 'password': password, } exists = self.UserModel._default_manager.db_manager(database).filter(username=username).exists() if not exists: self.UserModel._default_manager.db_manager(database).create_superuser(**user_data)
これで以下のようにワンランナーでスーパーユーザーを作成することができます。
$ python manage.py custom_createsuperuser --username admin --email admin@example.com --password admin
ついでにpytestで書いたユニットテストも掲載しておきます。
import pytest from django.core.management import CommandError, call_command from django.test.client import Client @pytest.mark.django_db @pytest.mark.parametrize('username,email,password', [ ('admin', 'admin@example.com', 'admin') ]) def test_success_case(username, email, password): call_command( 'createsuperuser_with_password', '--username', username, '--email', email, '--password', password ) client = Client() response = client.login(username=username, password=password) assert response is True @pytest.mark.django_db @pytest.mark.parametrize('username,email', [ ('admin', 'admin@example.com') ]) def test_CommandError_case(username, email): with pytest.raises(CommandError): call_command( 'createsuperuser_with_password', '--username', username, '--email', email )
参考: https://stackoverflow.com/questions/6244382/how-to-automate-createsuperuser-on-django
【Python】loggingのerror()とexception()の違い
loggingのerror()とexception()は同じ ERROR
レベルのロギング関数なのですが、どういった違いがあるのでしょうか?
結論はPython公式ドキュメントの「Logging HOWTO」に記載されています。
Logger.exception() は Logger.error() と似たログメッセージを作成します。違いは Logger.exception() がスタックトレースを一緒にダンプすることです。例外ハンドラでだけ使うようにしてください。
実際にコーディングして確かめてみます。
例外処理をまずはerror()でログ出力してみます。
ZeroDivisionError
の例外が投げられるようなコーディングをします。
import logging logger = logging.getLogger('example') handler = logging.StreamHandler() formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') handler.setFormatter(formatter) logger.addHandler(handler) try: result = 1 / 0 except ZeroDivisionError as e: logger.error(f'{e}')
これの出力は以下のようになりました。
2019-01-24 14:27:39,163 - example - ERROR - division by zero
続いて、exception()です。
try: result = 1 / 0 except ZeroDivisionError as e: logger.exception(f'{e}')
この出力は以下のようになりました。
2019-01-24 14:27:39,175 - example - ERROR - division by zero Traceback (most recent call last): File "<ipython-input-2-6a7fc51b65bc>", line 2, in <module> result = 1 / 0 ZeroDivisionError: division by zero
上記のように、exception() のログにはスタックトレースが出力されているのに対し、error() のログには確認できません。
実際に試してみると非常にシンプルな違いですね。
例外処理のとき、exception() でログを出力するとスタックトレースとともに詳細なログが出力されます。 よって、例外処理のときは exception() を、それ以外のときは error() を使うと良いということでした。
GitLab 11.6の新機能「Suggest Changes」が便利なのでオススメ
「Suggest Changes」は一言でいうと、レビューと修正がブラウザで完結しちゃう機能です。具体的には、
ということができます。GitHubでも同じような機能がリリースされています。
使い方は insert suggestion
というボタンを押して修正したいソースコードに書き換えるだけです。
詳細は以下のドキュメントをご確認ください。
タイポなどの細かい修正を提案したり複数の修正を提案したりする時に便利ですが、提案したコードでパイプラインが失敗したらかっこ悪いので用法用量にはお気をつけください。
あと、既知のバグかはわかりませんがハイライトのテーマがブラック系(特にMonokai)だと該当コードが見えにくいという罠があるので注意してください。
追記:
上記のバグですが、11.8で修正されるみたいです。 id:tnir さんにご指摘いただきました。
monokai/dark/solarized-darkでテストされていないというのはある気がしますし、あんまりdogfoodingでもsuggest changes使わないので気付かれにくいポイントではあったように思います。preview中の不具合は2/22リリースの11.8.0で修正されることになりました 🙇♂️🙇♂️🙇♂️https://t.co/2xuvXDbvgP #gitlab
— tnir / Takuya Noguchi #SnykCon (@tn961ir) January 24, 2019