#34716: Class methods from subclasses cannot be used as Field.default.
---------------------------------+------------------------------------
     Reporter:  Nicolò Intrieri  |                    Owner:  nobody
         Type:  Bug              |                   Status:  new
    Component:  Migrations       |                  Version:  4.2
     Severity:  Normal           |               Resolution:
     Keywords:                   |             Triage Stage:  Accepted
    Has patch:  0                |      Needs documentation:  0
  Needs tests:  0                |  Patch needs improvement:  0
Easy pickings:  0                |                    UI/UX:  0
---------------------------------+------------------------------------
Changes (by Mariusz Felisiak):

 * stage:  Unreviewed => Accepted


Old description:

> {{{
> #!div
>
> Given the following model:
>
>   {{{#!python
>
> 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:
>  {{{#!python
>     # ...
>       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".

New description:

 {{{
 #!div

 Given the following model:

   {{{#!python

 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:
  {{{#!python
     # ...
       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".

--

Comment:

 Thanks for the report. It seems that `FunctionTypeSerializer` should use
 `__qualname__` instead of `__name__`:
 {{{#!diff
 diff --git a/django/db/migrations/serializer.py
 b/django/db/migrations/serializer.py
 index d88cda6e20..06657ebaab 100644
 --- a/django/db/migrations/serializer.py
 +++ b/django/db/migrations/serializer.py
 @@ -168,7 +168,7 @@ class FunctionTypeSerializer(BaseSerializer):
          ):
              klass = self.value.__self__
              module = klass.__module__
 -            return "%s.%s.%s" % (module, klass.__name__,
 self.value.__name__), {
 +            return "%s.%s.%s" % (module, klass.__qualname__,
 self.value.__name__), {
                  "import %s" % module
              }
          # Further error checking

 }}}

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

-- 
Ticket URL: <https://code.djangoproject.com/ticket/34716#comment:1>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/01070189634cb06a-d5f11cea-e6c8-482c-94a3-8fb669e76fda-000000%40eu-central-1.amazonses.com.

Reply via email to