Сбой тестов Django после перехода на 1.2.5-проблема первичного ключа для дочерней модели



У меня есть модель ThreadedComment, которая наследуется от объекта model. ThreadedComment не имеет собственного уникального первичного ключа, полагаясь на промарный ключ объекта ("ID"). Вот как строится модель:



class Object(models.Model):
permalink = models.CharField(max_length=128)
status = models.IntegerField()
version = models.IntegerField()

class ThreadedComment(Object):
parent = models.ForeignKey('self', null=True, blank=True, default=None, related_name='children')
parent_object = models.OneToOneField(Object, parent_link=True)
# other fields follow


Это отлично работало до django 1.2.3, но когда я обновился до django 1.2.5 (1.3 имеет ту же проблему), это происходит, когда я пытаюсь запустить любой тест:



Error: Database test_db couldn't be flushed. Possible reasons:
* The database isn't running or isn't configured correctly.
* At least one of the expected database tables doesn't exist.
* The SQL was invalid.
Hint: Look at the output of 'django-admin.py sqlflush'. That's the SQL this command wasn't able to run.
The full error: relation "threadedcomments_threadedcomment_id_seq" does not exist
LINE 1: SELECT setval('"threadedcomments_threadedcomment_id_seq"', 1...


Проблема заключается в команде "sqlflush", которая генерирует и выполняет файл SQL. Проблемная линия это:



SELECT setval(pg_get_serial_sequence('"threadedcomments_threadedcomment"','id'), 1, false);


Это явно не удается, так как в этой таблице нет столбца" id".



Что интересно, версия django 1.2.3 выдает аналогичный результат:



SELECT setval('"threadedcomments_threadedcomment_id_seq"', 1, false);


Но тест все равно продолжается, поэтому я не заметил проблему раньше.

Что я здесь делаю не так? Является ли определение модели неверным, т. е. должен ли я иметь первичный ключ в threadedcomment, даже если мне не нужно, чтобы он имел отношение один к одному с объектом? И как получилось, что все шло отлично? с 1.0 по 1.1 до 1.2.3 и теперь прорывается в 1.2.5?

550   3  

3 ответов:

Это оказалось ошибкой Джанго. Подробности здесь: http://code.djangoproject.com/ticket/12728

И вот наш временный обходной путь: https://bitbucket.org/filmaster/filmaster-test/changeset/afbac905cf63

Я не могу воспроизвести его на trunk или 1.2.3; я создал свежий проект с приложением "threadedcomments" и моделями, которые вы опубликовали со следующим результатом:

BEGIN;
TRUNCATE "threadedcomments_threadedcomment", "auth_permission", "auth_group", "auth_group_permissions", "django_session", "auth_user_groups", "auth_user_user_permissions", "threadedcomments_object", "auth_message", "django_site", "auth_user", "django_content_type";
SELECT setval(pg_get_serial_sequence('"auth_permission"','id'), 1, false);
SELECT setval(pg_get_serial_sequence('"auth_group"','id'), 1, false);
SELECT setval(pg_get_serial_sequence('"auth_user"','id'), 1, false);
SELECT setval(pg_get_serial_sequence('"auth_message"','id'), 1, false);
SELECT setval(pg_get_serial_sequence('"django_content_type"','id'), 1, false);
SELECT setval(pg_get_serial_sequence('"django_site"','id'), 1, false);
SELECT setval(pg_get_serial_sequence('"threadedcomments_object"','id'), 1, false);
COMMIT;

Последовательность threadedcomments_threadedcomment_id_seq никогда не создается, и Джанго не пытается ее смыть. Я не думаю, что это ошибка, связанная с изменением версии (скорее, что-то, что всегда было там, но осталось незамеченным).

Вы сказали: "ThreadedComment не иметь уникальный первичный ключ собственными силами, полагаясь на promary ключ объекта [так в оригинале] ('идентификатор').- Джанго требует, чтобы одно поле было идентифицировано как первичный ключ. См. автоматическая полей первичного ключа.

Подробнее . . .

Функция pg_get_serial_sequence () возвращает имя последовательности, используемой конкретным столбцом. Таким образом, следующее утверждение означает: "получить имя последовательности, используемой для столбца 'id' в таблице 'threadedcomments_threadedcomment', установите для поля last_value последовательности значение 1 и возвращайте значение 1 при следующем вызове nextval ().

SELECT setval(pg_get_serial_sequence('"threadedcomments_threadedcomment"','id'), 1, false);

Но это утверждение

SELECT setval('"threadedcomments_threadedcomment_id_seq"', 1, false);

Означает, что " установите для поля last_value последовательности с именем 'threadedcomments_threadedcomment_id_seq' значение 1 и возвращайте значение 1 при следующем вызове nextval ()."

Я предполагаю, что алгоритм Django использует для именования последовательностей, измененных между версиями. Я видел, как другие системы делают подобные изменения, потому что идентификаторы созданные путем объединения имен таблиц и столбцов стали слишком длинными. Я думаю, что идентификаторы Oracle имеют ограничение в 30 символов; Ваш идентификатор-39 символов. Я видел, как Rails генерирует 70 + символьных идентификаторов, которые ломаются на PostgreSQL (ограничение 63 или 64 символа).

Comments

    Ничего не найдено.