K
K
KTF2020-10-02 12:44:39
Django
KTF, 2020-10-02 12:44:39

Why does a type mismatch error occur when creating objects in a back migration?

Hello. There are LanguageVariable and Page
models with Many-To-One connection:

class Page(models.Model):
    code = models.CharField(max_length=20)
    title = models.CharField(max_length=255, blank=True, default='', help_text='Page title displayed on a browser panel.')
    site = models.ForeignKey(Site, on_delete=models.PROTECT)
    objects = ModelManager()

    class Meta:
        unique_together = ('site', 'code')

    def __str__(self):
        return self.code

class LanguageVariable(models.Model):
    name = models.CharField(max_length=100)
    value = models.TextField(max_length=1000)
    page = models.ForeignKey(Page, related_name='lang_vars', on_delete=models.PROTECT)

    class Meta:
        db_table = 'cms_language_variable'
        unique_together = ('name', 'page')

    def __str__(self):
        return self.name

When migrating, you need to remove the old language variables for home pages (there are several of them according to the number of languages ​​on the site). Accordingly, these variables are added in the reverse migration code. Sample code:
test = {
    'test1': 'test1',
    'test2': 'test2',
}

def change_page(apps, schema_editor):
    LanguageVariable = apps.get_model('cms', 'LanguageVariable')
    LanguageVariable.objects.filter(name__in=test.keys(), page__code=PAGE_HOME).delete()

def revert_change_page(apps, schema_editor):
    Page = apps.get_model('cms', 'Page')
    LanguageVariable = apps.get_model('cms', 'LanguageVariable')

    home_pages = Page.objects.filter(code=PAGE_HOME)

    for page in home_pages:
        for lang_var_name, lang_var_value in test.items():
            lang_var = LanguageVariable()
            lang_var.name = lang_var_name
            lang_var.value = lang_var_value
            lang_var.page = page
            lang_var.save()

When I rollback the migration, I get the following error:
ValueError: Cannot assign "": "LanguageVariable.page" must be a "Page" instance.

When iterating , page has the class __fake__.Page type, and at first you might think that this is the problem, but if you add the same code to the direct migration, there will be no error, but the type will be the same.

The error occurs in django/db/models/fields/related_descriptors.py :
if value is not None and not isinstance(value, self.field.remote_field.model._meta.concrete_model):

For some unknown reason, isinstance returns False on the back migration even though the types are the same. I can not understand what could be the matter. The error occurred on Django 2.1, updating to the latest version did not change anything.
So far, as a solution, I used specifying the page by key: lang_var.page_id = page.id , but I would like to know what the problem is.

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question