Ticket #388 (closed defect: invalid)
schemamigration attempts to migrate GenericRelation
| Reported by: | jfunk@… | Owned by: | andrew |
|---|---|---|---|
| Priority: | major | Milestone: | 0.7.1 |
| Component: | migrations | Version: | 0.7-rc1 |
| Keywords: | Cc: |
Description
schemamigration --auto currently attempts to set up migrations for GenericRelations. This results in the following error during the actual migration:
File "/usr/lib/python2.6/site-packages/south/db/generic.py", line 205, in create_table
for field_name, field in fields
File "/usr/lib/python2.6/site-packages/south/db/generic.py", line 471, in column_sql
field = self._field_sanity(field)
File "/usr/lib/python2.6/site-packages/south/db/mysql.py", line 158, in _field_sanity
if self._db_type_for_alter_column(field).upper() in ["BLOB", "TEXT", "LONGTEXT"]:
AttributeError: 'NoneType' object has no attribute 'upper'
This happens because GenericRelations emulate relationships and do not actually represent db columns, so the db column type, as returned by field.type() is None.
South should probably skip any field where .type() returns None when detecting migrations.
If I remove the GenericRelation? lines from the resulting migration file, the migration succeeds and the model behaves properly.
Attachments
Change History
comment:2 Changed 3 years ago by SvartalF
I can reproduce it with my code.
I have this relation and a model field:
from django.contrib.contenttypes import generic
class GalleryRelation(generic.GenericRelation):
pass
def ManyToGalleriesField(*args, **kwargs):
return GalleryRelation(models.Gallery, *args, **kwargs)
and a model like this:
class Place(models.Model):
gallery = ManyToGalleriesField()
So in a migration I have this AttributeError? exception.
In the shell:
>>> from django.db.models import CharField >>> text = CharField(max_length=10) >>> text.db_type() 'varchar(10)' >>> from gallery import ManyToGalleriesField >>> g = ManyToGalleriesField() >>> print g.db_type() None
comment:3 follow-up: ↓ 4 Changed 3 years ago by andrew
I've tried that here, with these models (which you'll agree are the same layout as yours, but with all the ends):
class GenericThing(models.Model):
object_id = models.IntegerField()
content_type = models.ForeignKey(ContentType)
gfk = GenericForeignKey()
class GalleryRelation(generic.GenericRelation):
pass
def ManyToGalleriesField(*args, **kwargs):
return GalleryRelation(GenericThing, *args, **kwargs)
class Person(models.Model):
surname = models.CharField(max_length=60)
firstname = models.CharField(max_length=60)
gr = ManyToGalleriesField()
When I try to create the initial migration, I get:
$ ./manage.py schemamigration --initial bug388 /home/andrew/Programs/litret/southtut2/models.py:2: DeprecationWarning: the sha module is deprecated; use the hashlib module instead import sha Creating migrations directory at '/home/andrew/Programs/litret/bug388/migrations'... Creating __init__.py in '/home/andrew/Programs/litret/bug388/migrations'... ! Cannot freeze field 'bug388.person.gr' ! 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
Which is entirely correct; you'd then add a field ignoring rule as mentioned in the 0.7 docs here: http://south.aeracode.org/docs/customfields.html#field-name-patterns
South doesn't deal with unknown fields in 0.7; the point is that we always ask you about them, and in this case you would just tell South that it's not a real ManyToMany? field (which is where it appears in the model internals - note that M2Ms also have db_type = None, but they still have other database changes).
It sounds to me like you're using 0.6.2, or at least a migration from 0.6.2...
comment:4 in reply to: ↑ 3 Changed 3 years ago by SvartalF
My South copy was updated for trunk at 22nd of march (it has a "Version: 0.7-rc1" at PKG_INFO file), and I still have this error.
Initial migration is created correctly, but migrate myapp fails.
Also, I have an introspection rules for this field:
rules = [
(
(GalleryRelation,), [], {
"to": ["rel.to", {}],
"symmetrical": ["rel.symmetrical", {"default": True}],
"object_id_field": ["object_id_field_name", {"default": "object_id"}],
"content_type_field": ["content_type_field_name", {"default": "content_type"}],
"blank": ["blank", {"default": True}],
},
),
]
add_introspection_rules(rules, ['^gallery'])
comment:5 Changed 3 years ago by andrew
No, those kind of introspection rules aren't what you want - the GalleryRelation? field means nothing in database terms. You want to replace them with something like:
from south.modelsinspector import add_ignored_fields add_ignored_fields(["^gallery\.models\.GalleryRelation"])
What you've done is explicitly tell South that yes, it's fine to use this column in the database. That snippet tells South to just ignore it entirely.

I can't replicate this here; if I use --initial it ignores them, and if I use --auto after adding a GenericRelation? or GenericForeignKey? it says nothing has changed.
Are you sure you're using 0.7-rc1?