I have a model which has a nullable foreign key relation with itself (this 'self' can be any model which has this foreign key). This foreign key is a custom class which prevents cyclic relationships.
The call to super()
in the __init__
contains null=True
and blank=True
and therefor need to be included in the inspection rules of South. This makes at least the schemamigration work, but the migrate still fails.
Following code shows: the custom foreign key, the inspection rules and the model using the foreign key.
# Foreign key
class ParentField(models.ForeignKey)
def __init__(self, verbose_name=None, **kwargs):
super(ParentField, self).__init__('self', verbose_name=verbose_name, null=True, blank=True, **kwargs)
@staticmethod
def checkcyclic(object, attr):
'''Check for a cyclic relationship'''
pass
# Introspection rules
add_introspection_rules([
(
[ParentField],
[],
{
'null': ['null', {'default': True}],
'blank': ['blank', {'default': True}],
}
)
], ["^test\.models\.fields\.ParentField"])
# Model
class Relation(Model):
parent = ParentField(related_name='child_set')
Migrating gives the following error:
$ ./manage.py migrate
[..]
super(ParentField, self).__init__('self', verbose_name=verbose_name, null=True, blank=True, **kwargs)
TypeError: __init__() got multiple values for keyword argument 'to'
I've tried addding a rule like below, but that changed nothing.
'to': ['rel.to', {'default': 'test.models.Relation'}],
Can anyone tell me what I'm doing the wrong way or any hints to a solution for this?
In the end this solution worked for me, credits to Shai over at googlegroups:
South, when it tries to build an instance of your custom field, collects (using
the rules) values for the different kwargs of your class. One of these is the
"to"
argument; you see it specified in the migration code.
Then, it takes the values it collected and passes them to a constructor. So, effectively, you get the call
fields.ParentField(related_name='set', to=orm['module.ModelClass'])
However, inside your __init__
this gets translated to
models.ForeignKey('self', related_name='set', to=orm['module.ModelClass'])
So there are two values for the 'to'
argument -- the first is the positional
'self'
.
One solution, at least, is to do the same thing I recommended for the null and blank arguments -- add it into kwargs, rather than directly to the call.
kwargs.setdefault('to', 'self')