Django-guardian: django1.7の移行でassign_permを使用する

作成日 2014年11月13日  ·  10コメント  ·  ソース: django-guardian/django-guardian

次の移行コードを検討してください。

from django.db import models, migrations
from guardian.shortcuts import assign_perm

def assign_perms(apps, schema_editor):
    Group = apps.get_model("auth", "Group")
    for group in Group.objects.all():
        assign_perm('products.view_product', group)
        # assign_perm('products.view_product', group, product)

class Migration(migrations.Migration):

    operations = [
        migrations.RunPython(assign_perms),
    ]

この移行を適用すると、 assign_perm呼び出しでエラーが発生します。

guardian.exceptions.NotUserNorGroup: User/AnonymousUser or Group instance is required (got Group object)

最も参考になるコメント

他の人に役立つ場合に備えて、ここに投稿しますが、初期設定の移行のためにこの比較的一般的なassign_permメソッドを作成しました。いくつかの仮定を行いますが、おそらく役に立ちます。

def assign_perm(perm, user_or_group, obj=None, apps=None):
    permission_model = apps.get_model('auth', 'Permission')
    permission = permission_model.objects.get(codename=perm)

    # Assumes object permission models live in the same app as the model they govern
    # and are named like `ProjectUserObjectPermission`/`ProjectGroupObjectPermission`
    obj_permission_model = apps.get_model(obj._meta.app_label, '{}{}ObjectPermission'.format(
        obj._meta.object_name,
        user_or_group._meta.object_name,
    ))
    obj_permission_model.objects.create(
        # `object_pk` and `content_type_id` keys if you're not using direct foreign keys
        # https://django-guardian.readthedocs.io/en/stable/userguide/performance.html#direct-foreign-keys
        content_object=obj,
        permission=permission,
        **{
            user_or_group._meta.model_name: user_or_group
        }
    )

全てのコメント10件

+1

+1

+1

私は、インポートすることで、このエラーを修正Groupからdjango.contrib.authしかし、今(#333を参照)、データベースの変更を行っていないようで、。 それはdjango1.8とguardian1.3にありますが、誰かが1.7を試してみることができれば、それは素晴らしいことです。

移行スクリプトに2つのヘルパー関数を使用することになりました。
https://gist.github.com/xuhcc/67871719116bdc0fee6c
(django-guardian == 1.2.5)

残念ながら、1.8 /1.3にはまだ愛がありません。 ヘルパー関数を使用するとエラーが発生します
ValueError: Cannot query "project": Must be "ContentType" instance at

perm = Permission.objects.get(
            content_type=get_content_type(obj),
            codename=codename)

objは、次のように取得したprojectという名前のモデルのインスタンスです。

projs = get_objects_for_user(user, 'api.view_project')
        for proj in projs:
                assign_perm(apps, 'api.edit_project', user, proj)

残念ながら、マイグレーション内でassign_perms(またはマイグレーション自体にない他のスキーマ依存コード)を使用することは本当に悪い考えです。 それも機能しないのは驚きではありません。

ロジックでパーミッションモデルを見つけることが機能しない理由は、移行に必要なapps.get_model()によって返される正しいモデルを使用していない可能性があります。 これは修正可能かもしれません。

ただし、ここには解決できない根本的な問題があります。 つまり、データベースの移行では、 assign_perm()関数またはassign_perm()呼び出しの関数をシリアル化しようとはしません。 そのため、django-guardianの新しいバージョンでは、データベーススキーマを変更し、新しいスキーマを使用するようにassign_perm()を更新する可能性があります。 古いデータベーススキーマで新しいassign_perm()コードを実行しているため、古い移行は突然中断します。

実際、ロールなど、要求された機能の一部で、スキーマのこの変更が必要になる可能性があります。

これはおそらくあなたが探していた答えではありませんが、アクセス許可を設定するには、より低いレベルのデータベース操作を使用する必要があると思います。 これは、Permissiondbモデルとの直接の相互作用を意味します。 Djangoの移行では、移行外のデータベーススキーマに依存する機能にアクセスしないでください。 これには、dbモデルクラスのカスタム関数も含まれます。

おそらく、この制限はより適切に文書化される可能性があります。 プルリクエストを歓迎します。

そのため、このバグを閉じます。

こんにちは
1.4.4バージョンのpfguardianとdjango1.9.7でも同じ問題が発生します
移行内のassign_permは機能しません... :(
移行内で完全に修正したり、モンキーパッチを適用したりするにはどうすればよいですか?

ロジックでパーミッションモデルを見つけることが機能しない理由は、移行に必要なapps.get_model()によって返される正しいモデルを使用していない可能性があります。 これは修正可能かもしれません。

たぶん、認証グループをラップして、保護者グループのように動作させることができます。

他の人に役立つ場合に備えて、ここに投稿しますが、初期設定の移行のためにこの比較的一般的なassign_permメソッドを作成しました。いくつかの仮定を行いますが、おそらく役に立ちます。

def assign_perm(perm, user_or_group, obj=None, apps=None):
    permission_model = apps.get_model('auth', 'Permission')
    permission = permission_model.objects.get(codename=perm)

    # Assumes object permission models live in the same app as the model they govern
    # and are named like `ProjectUserObjectPermission`/`ProjectGroupObjectPermission`
    obj_permission_model = apps.get_model(obj._meta.app_label, '{}{}ObjectPermission'.format(
        obj._meta.object_name,
        user_or_group._meta.object_name,
    ))
    obj_permission_model.objects.create(
        # `object_pk` and `content_type_id` keys if you're not using direct foreign keys
        # https://django-guardian.readthedocs.io/en/stable/userguide/performance.html#direct-foreign-keys
        content_object=obj,
        permission=permission,
        **{
            user_or_group._meta.model_name: user_or_group
        }
    )
このページは役に立ちましたか?
0 / 5 - 0 評価

関連する問題

BenDevelopment picture BenDevelopment  ·  5コメント

ad-m picture ad-m  ·  13コメント

Dzejkob picture Dzejkob  ·  28コメント

g-as picture g-as  ·  10コメント

Allan-Nava picture Allan-Nava  ·  35コメント