Opened 16 months ago

Last modified 16 months ago

#34716 closed Bug

Class methods from subclasses cannot be used as Field.default. — at Version 1

Reported by: Nicolò Intrieri Owned by: nobody
Component: Migrations Version: 4.2
Severity: Normal Keywords:
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Mariusz Felisiak)

Given the following model:

  
class Profile(models.Model):

    class Capability(models.TextChoices):
        BASIC = ("BASIC", "Basic")
        PROFESSIONAL = ("PROFESSIONAL", "Professional")
        
        @classmethod
        def default(cls) -> list[str]:
            return [cls.BASIC]

    capabilities = ArrayField(
        models.CharField(choices=Capability.choices, max_length=30, blank=True),
        null=True,
        default=Capability.default
    )


The resulting migration contained the following:

   # ...
     migrations.AddField(
           model_name='profile',
           name='capabilities',
           field=django.contrib.postgres.fields.ArrayField(base_field=models.CharField(blank=True, choices=[('BASIC', 'Basic'), ('PROFESSIONAL', 'Professional')], max_length=30), default=appname.models.Capability.default, null=True, size=None),
       ),
   # ...

As you can see, migrations.AddField is passed as argument "default" a wrong value "appname.models.Capability.default", which leads to an error when trying to migrate. The right value should be "appname.models.Profile.Capability.default".

Change History (1)

comment:1 by Mariusz Felisiak, 16 months ago

Description: modified (diff)
Summary: Using subclass method as a callable for a field's default value results in wrong reference in the corresponding migrationClass methods from subclasses cannot be used as Field.default.
Triage Stage: UnreviewedAccepted

Thanks for the report. It seems that FunctionTypeSerializer should use __qualname__ instead of __name__:

  • django/db/migrations/serializer.py

    diff --git a/django/db/migrations/serializer.py b/django/db/migrations/serializer.py
    index d88cda6e20..06657ebaab 100644
    a b class FunctionTypeSerializer(BaseSerializer):  
    168168        ):
    169169            klass = self.value.__self__
    170170            module = klass.__module__
    171             return "%s.%s.%s" % (module, klass.__name__, self.value.__name__), {
     171            return "%s.%s.%s" % (module, klass.__qualname__, self.value.__name__), {
    172172                "import %s" % module
    173173            }
    174174        # Further error checking

Would you like to prepare a patch? (regression test is required)

Note: See TracTickets for help on using tickets.
Back to Top