Ich versuche, eine django-south migration zu einer vorhandenen Anwendung zu tun, um django-audit-log hinzuzufügen (um von Benutzern initiierte Änderungen eines Moduls zu verfolgen), aber es treten erhebliche Fehler auf. Insbesondere mit dem Feld action_user_id, das ein LastUserField ist (das den Benutzer speichert, der die Änderung angegeben hat, die verfolgt wird).django-south mit django-audit-log
Wenn ich von einem leeren Modell ausgehend war, konnte ich nur ein audit_log über hinzufügen:
from audit_log.models.managers import AuditLog
...
class SomeModel(models.Model)
...
audit_log = AuditLog()
Anwendung diese einfache Änderung und eine schemamigration in django-Süd zu tun gibt mir verstehend einen Fehler:
! Cannot freeze field 'myapp.mymodelauditlogentry.action_user'
! (this field has class audit_log.models.fields.LastUserField)
! South cannot introspect some fields; this is probably because they are custom
! fields. If they worked in 0.6 or below, this is because we have removed the
! models parser (it often broke things).
! To fix this, read http://south.aeracode.org/wiki/MyFieldsDontWork
Ich lese das MyFieldsDontWork Wiki (und die Custom Fields/Introspection Teile), aber es ist nicht 100% klar, was ich tun muss, um die Felder zum Funktionieren zu bringen.
Ich versuche, fügte hinzu:
from south.modelsinspector import add_introspection_rules
add_introspection_rules([], ["^audit_log\.models\.fields\.LastUserField"])
meiner models.py, die die ./manage.py schemamigration ein Migrationsskript zu erstellen erlaubt mit der vorherigen Fehler weggeht. Allerdings, wenn ich versuche zu migrieren (die Migration zu rechnen), erhalte ich folgende Fehler:
Running migrations for myapp:
- Migrating forwards to 0004_auto__add_mymodelauditlogentry.
> my_app:0004_auto__add_mymodelauditlogentry
Traceback (most recent call last):
File "./manage.py", line 11, in <module>
execute_manager(settings)
File "/usr/local/lib/python2.6/dist-packages/Django-1.2.3-py2.6.egg/django/core/management/__init__.py", line 438, in execute_manager
utility.execute()
File "/usr/local/lib/python2.6/dist-packages/Django-1.2.3-py2.6.egg/django/core/management/__init__.py", line 379, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/usr/local/lib/python2.6/dist-packages/Django-1.2.3-py2.6.egg/django/core/management/base.py", line 191, in run_from_argv
self.execute(*args, **options.__dict__)
File "/usr/local/lib/python2.6/dist-packages/Django-1.2.3-py2.6.egg/django/core/management/base.py", line 220, in execute
output = self.handle(*args, **options)
File "/usr/local/lib/python2.6/dist-packages/South-0.7.3-py2.6.egg/south/management/commands/migrate.py", line 105, in handle
ignore_ghosts = ignore_ghosts,
File "/usr/local/lib/python2.6/dist-packages/South-0.7.3-py2.6.egg/south/migration/__init__.py", line 191, in migrate_app
success = migrator.migrate_many(target, workplan, database)
File "/usr/local/lib/python2.6/dist-packages/South-0.7.3-py2.6.egg/south/migration/migrators.py", line 221, in migrate_many
result = migrator.__class__.migrate_many(migrator, target, migrations, database)
File "/usr/local/lib/python2.6/dist-packages/South-0.7.3-py2.6.egg/south/migration/migrators.py", line 292, in migrate_many
result = self.migrate(migration, database)
File "/usr/local/lib/python2.6/dist-packages/South-0.7.3-py2.6.egg/south/migration/migrators.py", line 125, in migrate
result = self.run(migration)
File "/usr/local/lib/python2.6/dist-packages/South-0.7.3-py2.6.egg/south/migration/migrators.py", line 93, in run
south.db.db.current_orm = self.orm(migration)
File "/usr/local/lib/python2.6/dist-packages/South-0.7.3-py2.6.egg/south/migration/migrators.py", line 246, in orm
return migration.orm()
File "/usr/local/lib/python2.6/dist-packages/South-0.7.3-py2.6.egg/south/utils.py", line 62, in method
value = function(self)
File "/usr/local/lib/python2.6/dist-packages/South-0.7.3-py2.6.egg/south/migration/base.py", line 422, in orm
return FakeORM(self.migration_class(), self.app_label())
File "/usr/local/lib/python2.6/dist-packages/South-0.7.3-py2.6.egg/south/orm.py", line 46, in FakeORM
_orm_cache[args] = _FakeORM(*args)
File "/usr/local/lib/python2.6/dist-packages/South-0.7.3-py2.6.egg/south/orm.py", line 125, in __init__
self.models[name] = self.make_model(app_label, model_name, data)
File "/usr/local/lib/python2.6/dist-packages/South-0.7.3-py2.6.egg/south/orm.py", line 318, in make_model
field = self.eval_in_context(code, app, extra_imports)
File "/usr/local/lib/python2.6/dist-packages/South-0.7.3-py2.6.egg/south/orm.py", line 236, in eval_in_context
return eval(code, globals(), fake_locals)
File "<string>", line 1, in <module>
File "/usr/local/lib/python2.6/dist-packages/django_audit_log-0.2.1-py2.6.egg/audit_log/models/fields.py", line 12, in __init__
super(LastUserField, self).__init__(User, null = True, **kwargs)
TypeError: __init__() got multiple values for keyword argument 'null'
EDIT (20.12 Uhr): Ich kann die schemamigration bewerben, wenn ich die Zeilen in dem models.py
from south.modelsinspector import add_introspection_rules, add_ignored_fields
add_ignored_fields(["^audit_log\.models\.fields\.LastUserField"])
außer dann die audit_log Middleware funktioniert nicht, da es kein Feld in myapp_mymodelauditlogentry, die Verweise „auth_user“ von „id“ action_user_id ganze Zahl ist. Dann wende ich manuell die SQL (SQLite Syntax, erhalten durch sqliteman auf neu erstellte Datenbank.)
ALTER TABLE "myapp_mymodelauditlogentry" ADD "action_user_id" integer REFERENCES "auth_user" ("id");
und es funktioniert. Ich werde immer noch das Kopfgeld geben, wenn jemand erklärt, wie ich das im Kontext von Django-South mit Migrationen/Introspektion tun soll, ohne auf rohen datenbankabhängigen SQL umsteigen zu müssen und dankbar zu sein.
Außerdem habe ich einen Index für action_user_id erstellt. Ich stelle fest, dass die normale Erstellung von Modellen mit führt zu einem Index
CREATE INDEX "myapp_mymodelauditlogentry_26679921" ON "myapp_mymodelauditlogentry" ("action_user_id")
genannt
ich erlegt, dass der Hash-26679921 mit '%x' % (abs(hash(('action_user_id',))) % 4294967296L,)
basierend auf dem Feldnamen erstellt wird und auf etwas anderes (so sollte nicht auf der Grundlage immer _26679921, es sei denn, die Datenbank erfordert, dass der lange Name abgeschnitten wird. Ich bin mir nicht sicher, ob die Namen des Index jemals wichtig sind; aber wollte in Sicherheit sein.
Das Problem ist nur, dass Süden nicht wissen, wie Sie Ihre Felder migrieren. Für benutzerdefinierte Felder müssen Sie eigene Introspektionsregeln hinzufügen, in denen Sie angeben, welche Parameter wichtig sind und welche ignoriert werden können. Wenn ich heute Abend Zeit habe, werde ich ein Beispiel schreiben, wie man die Introspektion richtig machen kann. – Wolph
@WoLpH: Ja, es ist das Problem, die Introspektion zur Arbeit zu bringen, aber währenddessen gab es glücklicherweise Dokumentation für Introspektion. Es war mir nicht klar, ein Anfänger in Schema-Migrationen/Django-South (sowie Django-Audit-Log). Die ersten paar Dinge, die ich versuchte, funktionierten nicht mit dem LastUserField. Ich wäre Ihnen dankbar, wenn Sie in sich selbst arbeiten können (also muss ich SQL nicht manuell injizieren), aber um ehrlich zu sein, habe ich aufgehört, mich selbst zu testen und habe mich anderen Problemen zugewandt. –
Ich war ziemlich beschäftigt, also hatte ich noch keine Zeit, Ihnen eine richtige Antwort zu geben. Bitte ertragen Sie mich etwas länger :) (oder jemand anders kann es erklären).Lange Rede, kurzer Sinn, es funktioniert nicht, weil Sie den Süden nicht über die Parameter informiert haben, so dass es ignoriert wird, was dazu führt, dass es zweimal übergeben wird. – Wolph