Ticket #388 (closed defect: invalid)

Opened 4 years ago

Last modified 3 years ago

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.

Change History

comment:1 Changed 4 years ago by andrew

  • Status changed from new to infoneeded
  • Milestone set to 0.7

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?

comment:2 Changed 4 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 4 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 4 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 4 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.

comment:6 Changed 4 years ago by andrew

  • Milestone changed from 0.7 to 0.7.1

comment:7 Changed 4 years ago by andrew

  • Status changed from infoneeded to closed
  • Resolution set to invalid
Note: See TracTickets for help on using tickets.