DjangoのFixtureで投入するユーザ・グループに権限を設定

はじめに

DjangoFixturedjango.contrib.authUserGroupPermissionを設定する方法を確認しました。

パーミッションの作成

まずは適当なパーミッションModel.Meta.permissionsで作成します。
myapp アプリの MyPermission モデルに perm1perm2 を用意しました。

class MyPermission(models.Model):
    class Meta:
        managed = False
        default_permissions = ()
        permissions = (
            ('perm1', '権限1'),
            ('perm2', '権限2'),
        )

マイグレーションすると、以下の通りPermissionモデルに perm1perm2 が追加されています。

$ python manage.py makemigrations
$ python manage.py migrate
$ python manage.py dbshell
sqlite> .header on
sqlite> select * from auth_permission where codename == 'perm1' or codename == 'perm2';
id|content_type_id|codename|name
33|9|perm1|権限1
34|9|perm2|権限2

ユーザの作成

以下のように modelauth.userpk に1からインクリメントした数値、 fields にユーザの情報を設定すればユーザを登録できます。

[
   {
      "model":"auth.user",
      "pk":1,
      "fields":{
         "last_name":"テスト",
         "first_name":"ユーザ",
         "email":"foo@example.com",
         "username":"foo@example.com"
      }
   }
]

では権限をどのようにして割り当てるかというと、user_permissionsフィールドに Permissionオブジェクトのキーを指定することになります。

"fields":{
   ...
   "user_permissions": [...]
}

しかしPermissionオブジェクトの id 値はマイグレーション時に動的に決定されるため推測することは困難です。 例えば上記で作成した権限 perm1perm2id はそれぞれ 3334 です。

ではどうするかというと、 id 値の代わりにナチュラルキーを使用します。
まさにこのような場面を想定し、Djangoはモデルのシリアライズナチュラルキーを使用する仕組みを実装しています。

docs.djangoproject.com

PermissionManagerには get_by_natural_key が実装されているため、静的な情報である codenameapp_label および model でオブジェクトを特定することができます。

class PermissionManager(models.Manager):
    use_in_migrations = True

    def get_by_natural_key(self, codename, app_label, model):
        return self.get(
            codename=codename,
            content_type=ContentType.objects.db_manager(self.db).get_by_natural_key(app_label, model),
        )

例えば perm1 の権限を与える場合には、 user_permissions["perm1", "myapp", "mypermission"] を指定すれば良いわけです。なお model は小文字で指定する必要があります。

[
   {
      "model":"auth.user",
      "pk":1,
      "fields":{
         "last_name":"テスト",
         "first_name":"ユーザ",
         "email":"foo@example.com",
         "username":"foo@example.com",
         "user_permissions": [
            ["perm1", "myapp", "mypermission"],
            ["perm2", "myapp", "mypermission"]
         ]
      }
   }
]

これで、権限を割り当てたユーザを作成することができました。

$ python manage.py loaddata auth_user.json
Installed 1 object(s) from 1 fixture(s)

$ python manage.py dbshell
sqlite> .header on
sqlite> select * from auth_user_user_permissions where user_id = 1;
id|user_id|permission_id
1|1|33
2|1|34

グループの作成

グループの場合は権限のフィールド名がpermissionsに変わるだけです。

[
   {
      "model":"auth.group",
      "pk":1,
      "fields":{
         "permissions":[
            ["perm1", "myapp", "mypermission"],
            ["perm2", "myapp", "mypermission"]
         ],
         "name":"テストグループ"
      }
   }
]