Я пытаюсь выполнить миграцию django-south в существующее приложение, чтобы добавить к нему django-audit-log (чтобы отслеживать изменения модуля, инициированные пользователем), но сталкиваюсь со значительными ошибками.В частности, с полем action_user_id, которое является LastUserField (в котором хранится пользователь, указавший отслеживаемое изменение).
Если бы я начинал с пустой модели, я мог бы просто добавить Audit_log через:
from audit_log.models.managers import AuditLog
...
class SomeModel(models.Model)
...
audit_log = AuditLog()
Применение этого простого изменения и выполнение схемы в django-south с пониманием вызывает ошибку:
! 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
Я прочитал вики MyFieldsDontWork (и части Custom Fields / Introspection), но егоне на 100% ясно, что мне нужно сделать, чтобы заставить поля работать.
Я пытаюсь добавить:
from south.modelsinspector import add_introspection_rules
add_introspection_rules([], ["^audit_log\.models\.fields\.LastUserField"])
в мой models.py, что позволило ./manage.py schemamigration дляСоздание сценария миграции с предыдущей ошибкой исчезает.Однако, когда я пытаюсь выполнить миграцию (чтобы применить миграцию), я получаю следующие ошибки:
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'
РЕДАКТИРОВАТЬ (12/20 полдень) : я могу применить схему миграции, если добавлюстроки для models.py
from south.modelsinspector import add_introspection_rules, add_ignored_fields
add_ignored_fields(["^audit_log\.models\.fields\.LastUserField"])
, за исключением того, что промежуточное программное обеспечение audit_log не работает, поскольку в myapp_mymodelauditlogentry нет целочисленного поля action_user_id, которое ссылается на «auth_user» с помощью «id».Затем я вручную применяю SQL (синтаксис sqlite; полученный с помощью sqliteman для вновь созданной базы данных.)
ALTER TABLE "myapp_mymodelauditlogentry" ADD "action_user_id" integer REFERENCES "auth_user" ("id");
, и он работает.Я по-прежнему буду вознаграждаться, если кто-то объяснит, как я должен делать это в контексте django-south с миграциями / самоанализом, без необходимости переходить к необработанному SQL, зависящему от базы данных, и буду благодарен.
Также я создал индекс для action_user_id.Я заметил, что обычное создание моделей с указателями приводит к индексу с именем
CREATE INDEX "myapp_mymodelauditlogentry_26679921" ON "myapp_mymodelauditlogentry" ("action_user_id")
. Я обнаружил, что хеш 26679921 создается на основе имени поля с '%x' % (abs(hash(('action_user_id',))) % 4294967296L,)
и не основан ни на чем другом (так всегда должно быть _26679921, если база данных не требует, чтобы длинное имя было обрезано).Я не уверен, имеют ли значение имена индекса;но хотел быть в безопасности.