[Django]-Can't get proper response from `issubclass()` when called with Django's `__fake__` model type inside migration

0👍

I don’t think it’s correct to stick to checking model mixin on the historical model because migrations don’t record which abstract base class your model inherits from at any given point in time and cannot really trace back that in any way. Suppose that your model inherits from MixinX in mutation 0001 but then you change it to MixinY. First of all no new migration will be generated through makemigrations. Second you can even delete MixinX so this should not really impact your existing migrations.

Instead, you can stick to checking fields (even your own field types) because the specific type of the field is recorded inside migrations. For example if we change django.db.models.UUIDField to MyUUIDField which inherits it then makemigrations creates new migration for that and the code below would be able to find the specific type of the field:

def gen_uuid(apps, schema_editor):
    app_name = basename(dirname(dirname(__file__)))
    models = apps.get_app_config(app_name).get_models()
    for model in models:
        uuid_fields = []
        for field in model._meta.get_fields():
            if not isinstance(field, UUIDField):  # or custom MyUUIDField
                continue
            uuid_fields.append(field)
        if not uuid_fields:
            continue
        for row in model.objects.all():
            for uuid_field in uuid_fields:
                setattr(row, uuid_field.get_attname(), uuid.uuid4())
            row.save(update_fields=[f.get_attname() for f in uuid_fields])

There is such statement in the Django docs:

In addition, the concrete base classes of the model are stored as pointers, so you must always keep base classes around for as long as there is a migration that contains a reference to them.

It actually means that if your base model is non-abstract then it will be stored in migration and probably there is the way to verify class hierarchy. However if the mixin is an abstract base model then it won’t. That’s why I would suggest to stick to checking field types in this case.

👤bellum

-1👍

To determine the parent classes of the historical models use apps.get_model method. It’s about the actual model class, rather than the historical model object.

from os.path import basename, dirname
import uuid
from common.models.uuid_mixin import UUIDModelMixin

def gen_uuid(apps, schema_editor):
    app_name = basename(dirname(dirname(__file__)))
    models = apps.get_app_config(app_name).get_models()

    uuid_models = []
    for model in models:
        actual_model = apps.get_model(app_label=app_name, model_name=model._meta.model_name)
        if issubclass(actual_model, UUIDModelMixin):
            uuid_models.append(actual_model)

    for model in uuid_models:
        for row in model.objects.all():
            row.uuid = uuid.uuid4()
            row.save(update_fields=['uuid'])

Leave a comment