Django-guardian: Usando assign_perm na migração do Django 1.7

Criado em 13 nov. 2014  ·  10Comentários  ·  Fonte: django-guardian/django-guardian

Considere o seguinte código de migração:

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),
    ]

Ao aplicar esta migração, assign_perm call dá um erro:

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

Comentários muito úteis

Estou postando isso aqui, caso seja útil para outra pessoa, mas escrevi este método relativamente genérico assign_perm para uma configuração de migração inicial, faz algumas suposições, mas provavelmente útil:

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
        }
    )

Todos 10 comentários

+1

+1

+1

Corrigi esse erro importando Group de django.contrib.auth , mas agora não parece estar fazendo nenhuma alteração no banco de dados (consulte # 333). Isso está no django 1.8 e no guardian 1.3, então se alguém pudesse experimentar o 1.7 seria ótimo

Acabei usando duas funções auxiliares para scripts de migração:
https://gist.github.com/xuhcc/67871719116bdc0fee6c
(django-guardião == 1.2.5)

Ainda sem amor com 1.8 / 1.3, infelizmente. Usando suas funções auxiliares, recebo o erro
ValueError: Cannot query "project": Must be "ContentType" instance em

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

obj é uma instância de um modelo chamado project que recebo assim:

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

Infelizmente, usar assign_perms dentro de migrações (ou qualquer outro código dependente de esquema que não seja na própria migração) é uma ideia realmente ruim. Não estou surpreso que também não funcione.

O motivo pelo qual não funciona provavelmente na lógica de encontrar o modelo de permissão não está usando o modelo correto retornado por apps.get_model() exigido para a migração. Isso pode ser corrigido.

No entanto, há um problema fundamental aqui que não pode ser resolvido. Ou seja, as migrações de banco de dados não tentam serializar a função assign_perm() ou qualquer uma das chamadas de funções assign_perm() . Portanto, uma versão posterior do django-guardian poderia alterar o esquema do banco de dados e atualizar assign_perm() para usar o novo esquema. Suas migrações antigas serão interrompidas repentinamente porque agora estão executando o novo código assign_perm() com o esquema de banco de dados antigo.

Na verdade, é possível que alguns dos recursos solicitados, como funções, possam exigir essa alteração no esquema.

Esta provavelmente não é a resposta que você estava procurando, no entanto, acho que você deve usar operações de banco de dados de nível inferior para definir as permissões. Com isso, quero dizer interação direta com os modelos de banco de dados de permissão. As migrações do Django não devem acessar funções dependentes do esquema do banco de dados fora da migração. Isso inclui funções personalizadas na classe de modelo db também.

Possivelmente, essa limitação poderia ser melhor documentada. Solicitações de pull são apreciadas.

Como tal, fechando este bug.

Olá
Eu tenho o mesmo problema com a versão 1.4.4 pf guardian e django 1.9.7
qualquer assign_perm dentro de migrações não funciona ... :(
tem alguma ideia de como isso pode ser totalmente consertado ou patcheado dentro das migrações?

O motivo pelo qual isso não funciona provavelmente na lógica de encontrar o modelo de permissão não está usando o modelo correto retornado por apps.get_model () necessário para a migração. Isso pode ser corrigido.

Talvez os grupos de autenticação possam ser agrupados para se comportar como um grupo de guardiões.

Estou postando isso aqui, caso seja útil para outra pessoa, mas escrevi este método relativamente genérico assign_perm para uma configuração de migração inicial, faz algumas suposições, mas provavelmente útil:

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
        }
    )
Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

Allan-Nava picture Allan-Nava  ·  4Comentários

g-as picture g-as  ·  10Comentários

Allan-Nava picture Allan-Nava  ·  35Comentários

johnthagen picture johnthagen  ·  9Comentários

Dzejkob picture Dzejkob  ·  28Comentários