Django-guardian: Uso de assign_perm en la migración de django 1.7

Creado en 13 nov. 2014  ·  10Comentarios  ·  Fuente: django-guardian/django-guardian

Considere el siguiente código de migración:

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

Al aplicar esta migración, la llamada assign_perm da un error:

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

Comentario más útil

Estoy publicando esto aquí en caso de que sea útil para alguien más, pero escribí este método assign_perm relativamente genérico para una migración de configuración inicial, hace algunas suposiciones pero probablemente sea ú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 comentarios

+1

+1

+1

Solucioné este error importando Group de django.contrib.auth , sin embargo, ahora no parece estar realizando ningún cambio en la base de datos (ver # 333). Eso es en django 1.8 y guardian 1.3, así que si alguien pudiera probar 1.7 sería genial

Terminé usando dos funciones auxiliares para los scripts de migración:
https://gist.github.com/xuhcc/67871719116bdc0fee6c
(django-guardian == 1.2.5)

Desafortunadamente, todavía no me encanta 1.8 / 1.3. Usando sus funciones auxiliares obtengo el error
ValueError: Cannot query "project": Must be "ContentType" instance en

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

obj es una instancia de un modelo llamado proyecto que obtengo así:

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

Desafortunadamente, usar assign_perms dentro de las migraciones (o cualquier otro código dependiente del esquema que no esté en la migración en sí) es una muy mala idea. No me sorprende que tampoco funcione.

La razón por la que no funciona es muy probable que en la lógica para encontrar el modelo de permisos no esté usando el modelo correcto devuelto por apps.get_model() requerido para la migración. Esto podría arreglarse.

Sin embargo, aquí hay un problema fundamental que no tiene solución. Es decir, las migraciones de la base de datos no intentan serializar la función assign_perm() ni ninguna de las funciones assign_perm() llamadas. Entonces, una versión posterior de django-guardian podría cambiar el esquema de la base de datos y actualizar assign_perm() para usar el nuevo esquema. Sus antiguas migraciones se romperán repentinamente porque ahora están ejecutando el nuevo código assign_perm() con el esquema de base de datos anterior.

De hecho, es posible que algunas de las características solicitadas, como los roles, requieran este cambio en el esquema.

Probablemente esta no sea la respuesta que estaba buscando, sin embargo, creo que debe usar operaciones de base de datos de nivel inferior para establecer los permisos. Con esto me refiero a la interacción directa con los modelos de Permission db. Las migraciones de Django no deberían acceder a funciones dependientes del esquema de la base de datos fuera de la migración. Esto también incluye funciones personalizadas en la clase de modelo db.

Posiblemente esta limitación podría documentarse mejor. Se agradecen las solicitudes de extracción.

Como tal, cerrando este error.

Hola
tengo el mismo problema con la versión 1.4.4 pf guardian y django 1.9.7
cualquier assign_perm dentro de las migraciones no funciona ... :(
¿Hay alguna idea de cómo se puede arreglar totalmente o parchear dentro de las migraciones?

La razón por la que no funciona es muy probable que en la lógica para encontrar el modelo de permiso no esté usando el modelo correcto devuelto por apps.get_model () requerido para la migración. Esto podría arreglarse.

Tal vez los grupos de autenticación podrían ajustarse para comportarse como un grupo guardián.

Estoy publicando esto aquí en caso de que sea útil para alguien más, pero escribí este método assign_perm relativamente genérico para una migración de configuración inicial, hace algunas suposiciones pero probablemente sea ú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
        }
    )
¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

Allan-Nava picture Allan-Nava  ·  35Comentarios

BenDevelopment picture BenDevelopment  ·  5Comentarios

David-OConnor picture David-OConnor  ·  6Comentarios

Allan-Nava picture Allan-Nava  ·  4Comentarios

brianmay picture brianmay  ·  16Comentarios