ForeignKey data type for certain derived model fields not calculated correctly
|Reported by:||Robby Dermody||Owned by:||nobody|
|Component:||Database layer (models, ORM)||Version:||1.0|
|Has patch:||no||Needs documentation:||no|
|Needs tests:||no||Patch needs improvement:||no|
I have a case where I want to make a custom "BigAutoField" model field. So, given newforms,
I do something like this in my own code:
class BigAutoField(fields.AutoField): empty_strings_allowed=False def get_internal_type(self): return "BigAutoField" def db_type(self): assert settings.DATABASE_ENGINE == 'mysql' return 'bigint UNSIGNED AUTO_INCREMENT'
I then change the appropriate parts of my model to use this BigAutoField in place
of Django's AutoField. Such as:
class Foo(models.Model): id = custom_model_fields.BigAutoField('ID', primary_key=True)
Then, I have Django generate the schema and populate the DB. Looking at the data type of this
'Foo' table, I see that ID is UNSIGNED BIGINT. Great. However, when I look at the data type
of any foreign keys that reference it, I see that they are still INTEGER.
So I went and looked at the SVN code. In django/db/models/fields/related.py around line 701,
def db_type(self): # The database column type of a ForeignKey is the column type # of the field to which it points. An exception is if the ForeignKey # points to an AutoField/PositiveIntegerField/PositiveSmallIntegerField, # in which case the column type is simply that of an IntegerField. # If the database needs similar types for key fields however, the only # thing we can do is making AutoField an IntegerField. rel_field = self.rel.get_related_field() if (isinstance(rel_field, AutoField) or (not connection.features.related_fields_match_type and isinstance(rel_field, (PositiveIntegerField, PositiveSmallIntegerField)))): return IntegerField().db_type() return rel_field.db_type()
So it looks like my model is falling into the trap of isinstance(AutoField) being True,
since it is derived from AutoField. Now the quick and dirty hack around this is to copy
AutoField from django/db/models/fields/init.py and make that the basis of my BigAutoField.
I can do that for now, but in the long run I'd like to avoid putting internal Django code
into my project.
So, what do you guys recommend happen here? I see this code in Django
I referenced being a problem for anyone that tries to make their own model fields that
derive from AutoField, PositiveIntegerField and PositiveSmallIntegerField.