1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

[Django] カスタムコマンドを作成しよう!

Posted at

概要

Djangoのカスタムコマンドの作成方法について解説します
今回は指定したシステムユーザの数分データを生成するカスタムコマンドを作成します

前提

  • Djangoのプロジェクトを作成済み

ディレクトリ構成

tree
・
└── application
     │   ├── __init__.py
    │   ├── admin.py
    │   ├── apps.py
    │   ├── management
    │   │   └── commands
    │   │       └── seed.py
    │   ├── migrations
    │   │   ├── 0001_initial.py
    │   │   └── __init__.py
    │   └── models.py
    └── manage.py

実装

今回は

  • models.py
  • seed.py

の順に実装していきます

models.py

システムユーザのmodelを作成します
AbstractUserについて詳細に知りたい方は以下の記事を参照してください

application/models.py
from django.contrib.auth.models import AbstractUser, Group
from django.contrib.auth.validators import UnicodeUsernameValidator
from django.core.validators import RegexValidator
from django.db import models


class User(AbstractUser):
    """システムユーザ"""

    username_validator = UnicodeUsernameValidator()

    # 不要なフィールドはNoneにすることができる
    first_name = None
    last_name = None
    date_joined = None
    id = models.AutoField(
        primary_key=True,
        db_comment="ID",
    )
    employee_number = models.CharField(
        unique=True,
        validators=[RegexValidator(r"^[0-9]{8}$")],
        max_length=8,
        # 管理者のログイン画面で社員番号と表示される
        verbose_name="社員番号",
        db_comment="社員番号",
    )
    username = models.CharField(
        max_length=150,
        unique=True,
        validators=[username_validator],
        db_comment="ユーザ名",
    )
    email = models.EmailField(
        max_length=254,
        unique=True,
        db_comment="メールアドレス",
    )
    created_at = models.DateTimeField(
        auto_now_add=True,
        db_comment="作成日",
    )
    updated_at = models.DateTimeField(
        auto_now=True,
        db_comment="更新日",
    )
    groups = models.ForeignKey(
        Group,
        on_delete=models.PROTECT,
        related_name="users",
        db_comment="社員権限テーブル外部キー",
    )

    USERNAME_FIELD = "employee_number"
    REQUIRED_FIELDS = ["email", "username"]

    class Meta:
        ordering = ["employee_number"]
        db_table = "User"
        db_table_comment = "システムユーザ"

    def __str__(self):
        return self.username

seed.py

指定したシステムユーザの数分データを生成するカスタムコマンドを作成します
Djangoでカスタムコマンドを作成する際はmanagement/commands配下にPythonファイルを作成します
作成したファイル名がそのままコマンドになります
また、ディレクトリ配下のファイルの先頭に_を入れるとカスタムコマンドとして認識されなくなります

application/management/commands/seed.py
from django.contrib.auth.models import Group
from django.core.management.base import BaseCommand

from application.models import User


class Command(BaseCommand):
    help = "Seeds the database with initial data"

    def add_arguments(self, parser):
        """システムユーザの数を指定するオプション

        Args:
            parser : オプションを追加するためのparser
        """
        parser.add_argument(
            "--users",
            type=int,
            help="Specify the amount of users. The default amount of users will be 10",
        )

    def handle(self, *args, **options):
        """システムユーザを作成するコマンド"""
        Group.objects.update_or_create(
            id=1,
            name="管理者",
        )
        Group.objects.update_or_create(
            id=2,
            name="一般",
        )
        users = options["users"]
        if not users:
            users = 10
        print(f"Creating {users} users")
        for id in range(1, users + 1):
            try:
                user = User.objects.get(id=id)
            except User.DoesNotExist:
                user = User.objects.create_user(
                    id=id,
                    username=f"テストユーザ{id}",
                    employee_number=str(id).zfill(8),
                    email=f"example{id}.com",
                    groups=Group.objects.get(name="管理者"),
                )
            user.set_password("test")
            user.save()
            print(f"Created {user}")
        print(f"Successfully created {users} users")

一つずつ解説します

add_arguments

今回はコマンドに作成するユーザの数を指定するオプションを付与します
オプション名、型、ヘルパーテキストを指定できます

    def add_arguments(self, parser):
        """システムユーザの数を指定するオプション

        Args:
            parser : オプションを追加するためのparser
        """
        parser.add_argument(
            "--users",
            type=int,
            help="Specify the amount of users. The default amount of users will be 10",
        )

handle

handle内に実際の処理を記載します
**options内に使用したオプションの値が配列として格納されているのでhandle内で使用できます
今回はオプションを指定しなかったらデフォルトでユーザを10人作成し、オプションを指定したら指定した分だけユーザを作成する処理を記載します

    def handle(self, *args, **options):
        """システムユーザを作成するコマンド"""
        Group.objects.update_or_create(
            id=1,
            name="管理者",
        )
        Group.objects.update_or_create(
            id=2,
            name="一般",
        )
        users = options["users"]
        if not users:
            users = 10
        print(f"Creating {users} users")
        for id in range(1, users + 1):
            try:
                user = User.objects.get(id=id)
            except User.DoesNotExist:
                user = User.objects.create_user(
                    id=id,
                    username=f"テストユーザ{id}",
                    employee_number=str(id).zfill(8),
                    email=f"example{id}.com",
                    groups=Group.objects.get(name="管理者"),
                )
            user.set_password("test")
            user.save()
            print(f"Created {user}")
        print(f"Successfully created {users} users")

コマンドを実行してみよう!

作成したカスタムコマンドのhelpを見てみましょう

python manage.py seed --help

以下のようにコマンドとオプションのヘルパーテキストが表示されていることが確認できました

usage: manage.py seed [-h] [--users USERS] [--version] [-v {0,1,2,3}] [--settings SETTINGS] [--pythonpath PYTHONPATH] [--traceback] [--no-color] [--force-color] [--skip-checks]

Seeds the database with initial data

options:
  -h, --help            show this help message and exit
  --users USERS         Specify the amount of users. The default amount of users will be 10
  --version             Show program's version number and exit.
  -v {0,1,2,3}, --verbosity {0,1,2,3}
                        Verbosity level; 0=minimal output, 1=normal output, 2=verbose output, 3=very verbose output
  --settings SETTINGS   The Python path to a settings module, e.g. "myproject.settings.main". If this isn't provided, the DJANGO_SETTINGS_MODULE environment variable will be used.
  --pythonpath PYTHONPATH
                        A directory to add to the Python path, e.g. "/home/djangoprojects/myproject".
  --traceback           Raise on CommandError exceptions.
  --no-color            Don't colorize the command output.
  --force-color         Force colorization of the command output.
  --skip-checks         Skip system checks.

コマンドを実行します
以下のようにログが出力され、システムユーザが作成されたら成功です

python manage.py seed --users 20
Creating 20 users
Created テストユーザ1
Created テストユーザ2
Created テストユーザ3
Created テストユーザ4
Created テストユーザ5
Created テストユーザ6
Created テストユーザ7
Created テストユーザ8
Created テストユーザ9
Created テストユーザ10
Created テストユーザ11
Created テストユーザ12
Created テストユーザ13
Created テストユーザ14
Created テストユーザ15
Created テストユーザ16
Created テストユーザ17
Created テストユーザ18
Created テストユーザ19
Created テストユーザ20
Successfully created 20 users

Userテーブルの中は以下の通りです

django=# SELECT * FROM "User" order by id;
                                         password                                         | last_login | is_superuser | is_staff | is_active | id | employee_number |    username    |     emai
l     |          created_at           |          updated_at           | groups_id 
------------------------------------------------------------------------------------------+------------+--------------+----------+-----------+----+-----------------+----------------+---------
------+-------------------------------+-------------------------------+-----------
 pbkdf2_sha256$600000$N70GCTI2t5PvPv1iPh7IgB$n2NVOLXuxvSj29381p9DSvptAPIZSjKzPocQ3VKY2BA= |            | f            | f        | t         |  1 | 00000001        | テストユーザ1  | example1
.com  | 2024-02-04 10:42:05.67779+00  | 2024-02-04 10:42:06.031773+00 |         1
 pbkdf2_sha256$600000$N3fBdPCRjXLOBD2k3toyUt$gkYgtUTqsF6Ck5+AD6IApL83/NvQWFmVJlrxLEkEv/E= |            | f            | f        | t         |  2 | 00000002        | テストユーザ2  | example2
.com  | 2024-02-04 10:42:06.052773+00 | 2024-02-04 10:42:06.441644+00 |         1
 pbkdf2_sha256$600000$a9pkl6ZoaWvyr2xjb6njOQ$581cVCTfw4sVp0w9sbnBe5zMrnaLgIdZ3vE+8TZb+ME= |            | f            | f        | t         |  3 | 00000003        | テストユーザ3  | example3
.com  | 2024-02-04 10:42:06.451707+00 | 2024-02-04 10:42:06.826803+00 |         1
 pbkdf2_sha256$600000$mkfQol0fUYFyYfVLeQfjjX$0oEiSuhOnYPnIHRwhupbwOVMxmFMXsWJwAdmc3Q+qDs= |            | f            | f        | t         |  4 | 00000004        | テストユーザ4  | example4
.com  | 2024-02-04 10:42:06.835912+00 | 2024-02-04 10:42:07.272309+00 |         1
 pbkdf2_sha256$600000$84yicBdzakaQcBKaxXspdJ$0WcDga1WTUZVEQuWlwERoErqIYnBFoqThw9LEhwqr0g= |            | f            | f        | t         |  5 | 00000005        | テストユーザ5  | example5
.com  | 2024-02-04 10:42:07.279547+00 | 2024-02-04 10:42:07.619245+00 |         1
 pbkdf2_sha256$600000$iiUhfF22vlJem5zsq2LQ9W$Jespi8m5ekf7xamLJF5s8e4OKNCjZSalgE6LFpXn4/w= |            | f            | f        | t         |  6 | 00000006        | テストユーザ6  | example6
.com  | 2024-02-04 10:42:07.628706+00 | 2024-02-04 10:42:07.993764+00 |         1
 pbkdf2_sha256$600000$VUNr6RgiBd9kN9SbPMYO1i$dOmYRBHzfo7+F4YTh8drmKb4WKkLPiALymsd/ZzXKlw= |            | f            | f        | t         |  7 | 00000007        | テストユーザ7  | example7
.com  | 2024-02-04 10:42:08.003249+00 | 2024-02-04 10:42:08.351413+00 |         1
 pbkdf2_sha256$600000$rE0Y1GWkpDwWCUbOnhI3OU$YaDCdQVUZCkIxpbsd3bUJWkLyLT7NlNIJF8mBRFzhCk= |            | f            | f        | t         |  8 | 00000008        | テストユーザ8  | example8
.com  | 2024-02-04 10:42:08.358768+00 | 2024-02-04 10:42:08.688046+00 |         1
 pbkdf2_sha256$600000$XeB3OaXr9UPCtNxYkeuGcW$d0Rv3mwnWYeDMniN6t3L6GZWhUs7wvXovNadRpIVSPo= |            | f            | f        | t         |  9 | 00000009        | テストユーザ9  | example9
.com  | 2024-02-04 10:42:08.696455+00 | 2024-02-04 10:42:09.036743+00 |         1
 pbkdf2_sha256$600000$ScENbjJGpqiyi59gd3fhOC$FsDD9cwnJBFkO4ZSn9UqoNmWj041A8tSqQsg3WXBujw= |            | f            | f        | t         | 10 | 00000010        | テストユーザ10 | example1
0.com | 2024-02-04 10:42:09.046133+00 | 2024-02-04 10:42:09.486939+00 |         1
 pbkdf2_sha256$600000$bILciKYVYW44L9aoQMnDae$4hNdrPVl2wplKIhUiwbOBc88QTQc3zFCkbDvBCUiZ8w= |            | f            | f        | t         | 11 | 00000011        | テストユーザ11 | example1
1.com | 2024-02-04 10:42:09.497018+00 | 2024-02-04 10:42:10.017096+00 |         1
 pbkdf2_sha256$600000$638VoeGyOVpTIBPXgtDovq$fvzUy9Y/wU89znr1tEdL6oaZ64oty4B1t8lHpok8w3U= |            | f            | f        | t         | 12 | 00000012        | テストユーザ12 | example1
2.com | 2024-02-04 10:42:10.027721+00 | 2024-02-04 10:42:10.476937+00 |         1
 pbkdf2_sha256$600000$Jcm1530zHbIc5rJAJsZZAX$kDlFDNi5+NJtPWhHnGE76GyRG8xMcIM1GHiUgYnMSoA= |            | f            | f        | t         | 13 | 00000013        | テストユーザ13 | example1
3.com | 2024-02-04 10:42:10.485936+00 | 2024-02-04 10:42:10.90018+00  |         1
 pbkdf2_sha256$600000$AwTHyMTCCAh5autJc8zbBw$LUmDNCo0AAS/3FvDs9UDD2WIv7wAKShsra4iDhiOjxo= |            | f            | f        | t         | 14 | 00000014        | テストユーザ14 | example1
4.com | 2024-02-04 10:42:10.909085+00 | 2024-02-04 10:42:11.293215+00 |         1
 pbkdf2_sha256$600000$aUMjLRU5mm5yxWRL9iCMiX$a5CzTJ+2ieR+fGtesWtD/qkgfeXZzoHTaxzaxUld7ZE= |            | f            | f        | t         | 15 | 00000015        | テストユーザ15 | example1
5.com | 2024-02-04 10:42:11.302117+00 | 2024-02-04 10:42:11.681076+00 |         1
 pbkdf2_sha256$600000$tZMApEQgW92UhSnUYf3qmG$y+DtjW6iWuvZK75B018UJnokGy6mf6JqiMUiA5/yqiQ= |            | f            | f        | t         | 16 | 00000016        | テストユーザ16 | example1
6.com | 2024-02-04 10:42:11.690464+00 | 2024-02-04 10:42:12.143705+00 |         1
 pbkdf2_sha256$600000$UP2BS5Jy6Ypc8y96A7Ugwc$o1WVEXX78fpPbeMRPEAH/ShVYAKZhJv2saJXl7CeeNQ= |            | f            | f        | t         | 17 | 00000017        | テストユーザ17 | example1
7.com | 2024-02-04 10:42:12.153523+00 | 2024-02-04 10:42:12.50654+00  |         1
 pbkdf2_sha256$600000$r1KShSqKn6NRV1fV32hNQW$sfdxcC36lC+FwUSklCewsfIEkFy0LjAAJrN47RT7IgI= |            | f            | f        | t         | 18 | 00000018        | テストユーザ18 | example1
8.com | 2024-02-04 10:42:12.5147+00   | 2024-02-04 10:42:12.863796+00 |         1
 pbkdf2_sha256$600000$XS97oafQ3iujXqWYpKsVWF$JpCrzogirBtDZpRUBEjvYdqiUq7ToydKuz6gICj7Q40= |            | f            | f        | t         | 19 | 00000019        | テストユーザ19 | example1
9.com | 2024-02-04 10:42:12.871577+00 | 2024-02-04 10:42:13.228192+00 |         1
 pbkdf2_sha256$600000$wUOAM4OuTngr5uSV6UT6GC$hd5tpKPdFFkdNSnhXRwxWJ1MIgj85ms+qBIg2jiWU3I= |            | f            | f        | t         | 20 | 00000020        | テストユーザ20 | example2
0.com | 2024-02-04 10:42:13.23653+00  | 2024-02-04 10:42:13.622156+00 |         1
(20 rows)

参考

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?