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