Django-guardian: Verwenden von Assign_perm bei der Django 1.7-Migration

Erstellt am 13. Nov. 2014  ·  10Kommentare  ·  Quelle: django-guardian/django-guardian

Betrachten Sie den folgenden Migrationscode:

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

Beim Anwenden dieser Migration gibt der Aufruf von assign_perm einen Fehler aus:

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

Hilfreichster Kommentar

Ich poste dies hier für den Fall, dass es für andere nützlich ist, aber ich habe diese relativ generische Methode assign_perm für eine anfängliche Einrichtungsmigration geschrieben, die ein paar Annahmen macht, aber wahrscheinlich hilfreich ist:

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

Alle 10 Kommentare

+1

+1

+1

Ich habe diesen Fehler behoben, indem ich Group aus django.contrib.auth importiert habe, aber es scheint jetzt keine Änderungen in der Datenbank vorzunehmen (siehe #333). Das ist auf Django 1.8 und Guardian 1.3, also wenn jemand 1.7 ausprobieren könnte, wäre das großartig

Ich habe am Ende zwei Hilfsfunktionen für Migrationsskripte verwendet:
https://gist.github.com/xuhcc/67871719116bdc0fee6c
(django-wächter==1.2.5)

Leider immer noch keine Liebe mit 1.8/1.3. Mit deinen Hilfsfunktionen bekomme ich den Fehler
ValueError: Cannot query "project": Must be "ContentType" instance um

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

obj ist eine Instanz eines Modells namens project, das ich wie folgt erhalte:

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

Leider ist die Verwendung von Assign_perms innerhalb von Migrationen (oder jedem anderen schemaabhängigen Code, der nicht in der Migration selbst enthalten ist) eine wirklich schlechte Idee. Wundert mich auch nicht, dass es nicht funktioniert.

Der Grund, warum es in der Logik zum Auffinden des Berechtigungsmodells höchstwahrscheinlich nicht funktioniert, liegt darin, dass nicht das richtige Modell verwendet wird, das von apps.get_model() das für die Migration erforderlich ist. Dies kann möglicherweise behoben werden.

Allerdings gibt es hier ein grundsätzliches Problem, das nicht lösbar ist. Das heißt, die Datenbankmigrationen versuchen nicht, die assign_perm() Funktion oder eine der assign_perm() Funktionsaufrufe zu serialisieren. Eine neuere Version von django-guardian könnte also das Datenbankschema ändern und assign_perm() aktualisieren, um das neue Schema zu verwenden. Ihre alten Migrationen werden plötzlich kaputt gehen, weil sie jetzt den neuen assign_perm() Code mit dem alten Datenbankschema ausführen.

Tatsächlich ist es möglich, dass einige der angeforderten Funktionen, z. B. Rollen, diese Änderung im Schema erfordern.

Dies ist wahrscheinlich nicht die Antwort, nach der Sie gesucht haben, aber ich denke, Sie müssen Datenbankvorgänge auf niedrigerer Ebene verwenden, um die Berechtigungen festzulegen. Damit meine ich die direkte Interaktion mit den Permission-DB-Modellen. Django-Migrationen sollten nicht auf datenbankschemaabhängige Funktionen außerhalb der Migration zugreifen. Dies schließt auch benutzerdefinierte Funktionen für die db-Modellklasse ein.

Möglicherweise könnte diese Einschränkung besser dokumentiert werden. Pull-Requests erwünscht.

Schließen Sie diesen Fehler.

Hallo
ich habe das gleiche problem mit 1.4.4 version pf guardian und django 1.9.7
irgendein Assign_perm innerhalb von Migrationen funktioniert nicht... :(
Haben Sie eine Idee, wie es vollständig behoben oder Affen innerhalb von Migrationen gepatcht werden kann?

Der Grund, warum es in der Logik zum Auffinden des Berechtigungsmodells höchstwahrscheinlich nicht funktioniert, liegt darin, dass nicht das richtige Modell verwendet wird, das von apps.get_model() zurückgegeben wird, das für die Migration erforderlich ist. Dies kann möglicherweise behoben werden.

Vielleicht könnten Auth-Gruppen so verpackt werden, dass sie sich wie eine Wächtergruppe verhalten.

Ich poste dies hier für den Fall, dass es für andere nützlich ist, aber ich habe diese relativ generische Methode assign_perm für eine anfängliche Einrichtungsmigration geschrieben, die ein paar Annahmen macht, aber wahrscheinlich hilfreich ist:

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
        }
    )
War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

brianmay picture brianmay  ·  16Kommentare

Allan-Nava picture Allan-Nava  ·  35Kommentare

David-OConnor picture David-OConnor  ·  6Kommentare

lukaszb picture lukaszb  ·  14Kommentare

ad-m picture ad-m  ·  13Kommentare