Django tests failing after migrating to 1.2.5 - primary key issue for child model
I have a model ThreadedComment that inherits from model Object. ThreadedComment does not have a unique primary key of its own, relying on Object's promary key ("ID"). This is how the model is constructed:
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
This worked great until django 1.2.3 but when I upgraded to django 1.2.5 (1.3 has the same problem), this happens when I'm trying to run any test:
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...
The problem is with "sqlflush" command that generates and executes an SQL file. The problematic line is:
SELECT setval(pg_get_serial_sequence('"threadedcomments_threadedcomment"','id'), 1, false);
This obviously fails as there is no "id" column in that table.
开发者_如何学JAVAWhat is intersting, the django 1.2.3 version produces a similar output:
SELECT setval('"threadedcomments_threadedcomment_id_seq"', 1, false);
but the test goes on anyway so I did not notice the issue before.
What am I doing wrong here? Is the model definition incorrect, i.e. do I need to have a primary key in threadedcomment even though I don't need it having a one-to-one relationship with object? And how come it worked fine all the way from 1.0 through 1.1 till 1.2.3 and now breaks in 1.2.5?
This turned out to be a django bug. Details here: http://code.djangoproject.com/ticket/12728
And here is our temporary workaround: https://bitbucket.org/filmaster/filmaster-test/changeset/afbac905cf63
I can't reproduce it on trunk or 1.2.3; I created a fresh project with app 'threadedcomments' and the models you posted with following result:
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;
Sequence threadedcomments_threadedcomment_id_seq
is never created and Django doesn't try to flush it. I don't think it's a version change related bug (rather something that was always there, but went unnoticed).
You said, "ThreadedComment does not have a unique primary key of its own, relying on Object's promary [sic] key ('ID')." Django requires one field to be identified as a primary key. See Automatic primary key fields.
More details . . .
The function pg_get_serial_sequence() returns the name of the sequence used by a specific column. So the following statement means, "Get the name of the sequence used for the 'id' column in the table 'threadedcomments_threadedcomment', set the sequence's last_value field to 1, and return 1 the next time nextval() is called.
SELECT setval(pg_get_serial_sequence('"threadedcomments_threadedcomment"','id'), 1, false);
But this statement
SELECT setval('"threadedcomments_threadedcomment_id_seq"', 1, false);
means, "Set the last_value field of the sequence named 'threadedcomments_threadedcomment_id_seq' to 1, and return 1 the next time nextval() is called."
My guess is that the algorithm Django uses to name sequences changed between versions. I've seen other systems make similar changes because identifiers built up by concatenating table and column names became too long. I think Oracle identifiers have a 30-character limit; your identifier is 39 characters. I've seen Rails generate 70+ character identifiers, which break on PostgreSQL (63 or 64 character limit).
精彩评论