Skip to content

django-simple-history does not respect 'deconstruct' kwargs for custom foreignkey fields #431

Closed
@patrick4g

Description

@patrick4g

Describe the bug
After subclassing ForeignKey to override get_attname, and defining a deconstruct method to carry the additional parameter, makemigrations creates the correct migrations but django-simple-history ignores the extra parameters. The resulting models are unusable. A custom migration fixes the issue but will be replaced on the next makemigrations operation.

The custom foreign key field is motivated and inspired by:
https://stackoverflow.com/questions/21524830/modifying-djangos-default-id-suffix-for-related-objects/24427909#24427909

To Reproduce
Steps to reproduce the behavior:

Deconstruct, as defined in Django docs here, is used to carry the attr_name argument into the migrations. Here is the class:

class CustomAttrNameForeignKey(models.ForeignKey):
    def __init__(self, *args, **kwargs):
        self.attr_name = kwargs.pop('attr_name', None)
        super().__init__(*args, **kwargs)

    def get_attname(self):
        return self.attr_name or super().get_attname()

    def deconstruct(self):
        name, path, args, kwargs = super().deconstruct()
        if self.attr_name:
            kwargs['attr_name'] = self.attr_name
        return name, path, args, kwargs

Expected behavior
When running make migration, Django creates 2 migrations as expected. One for the model and one for the historical model. However, the migration associated with the historical model does not have the needed 'attr_name' argument. This makes all operations (save, get_or_create, etc.) on model instances fail.

Here is an example of the generated migration code:

        migrations.AlterField(
            model_name='mymodel',
            name='status_fk', 
            field=CustomAttrNameForeignKey(attr_name='status', db_column='status', to='MyStatusModel'),
        ),
        migrations.AlterField(
            model_name='historicalmymodel',
            name='status_fk',
            field=CustomAttrNameForeignKey(blank=True, db_column='status', db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='MyStatusModel'),
        ),

Environment (please complete the following information):

  • OS: Ubuntu 16.04
  • Django Simple History Version: 2.1.1
  • Django Version: 1.11.6
  • Database Version: PostgreSQL 9.6.6

Metadata

Metadata

Assignees

No one assigned

    Labels

    acceptedIssue accepted for completionbugIssues related to confirmed bugs

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions