﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
33914	App level default_auto_field is ignored for m2m through tables	Borislav Ivanov	nobody	"When default_auto_field is defined on app level, it is ignored for
m2m through tables. This effectively defaults them to what is defined
in DEFAULT_AUTO_FIELD setting.

This happens in two different code paths, ultimately affecting
Options::_get_default_pk_class:

1. When AppConfigStub is supplied instead of AppConfig it is stripped from most of the properties including default_auto_field.
2. When the first migration for a given app is applied, we don't get any app config as it is lazily registered in StateApps::register_models. As this is the first model for this app, the config is no there yet.

Here's modified configuration for polls app that demonstrates the issue:

mysite/settings.py:
{{{#!python
...
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'empty',
    }
}
...
DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
}}}

mysite/polls/apps.py:
{{{#!python
...
class PollsConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'polls'
}}}

mysite/polls/models.py:
{{{#!python
...
class KlassA(models.Model):
    field_a = models.CharField(max_length=200)


class KlassB(models.Model):
    field_b = models.CharField(max_length=200)
    m2m_to_a = models.ManyToManyField(
        KlassA, blank=True
    )

}}}

Then run `makemigrations` and `sqlmigrate polls 0001_initial`:
{{{
BEGIN;
--
-- Create model KlassA
--
CREATE TABLE ""polls_klassa"" (""id"" bigserial NOT NULL PRIMARY KEY, ""field_a"" varchar(200) NOT NULL);
--
-- Create model KlassB
--
CREATE TABLE ""polls_klassb"" (""id"" bigserial NOT NULL PRIMARY KEY, ""field_b"" varchar(200) NOT NULL);
CREATE TABLE ""polls_klassb_m2m_to_a"" (""id"" serial NOT NULL PRIMARY KEY, ""klassb_id"" bigint NOT NULL, ""klassa_id"" bigint NOT NULL);
ALTER TABLE ""polls_klassb_m2m_to_a"" ADD CONSTRAINT ""polls_klassb_m2m_to_a_klassb_id_klassa_id_05b47d06_uniq"" UNIQUE (""klassb_id"", ""klassa_id"");
ALTER TABLE ""polls_klassb_m2m_to_a"" ADD CONSTRAINT ""polls_klassb_m2m_to_a_klassb_id_58ef37e1_fk_polls_klassb_id"" FOREIGN KEY (""klassb_id"") REFERENCES ""polls_klassb"" (""id"") DEFERRABLE INITIALLY DEFERRED;
ALTER TABLE ""polls_klassb_m2m_to_a"" ADD CONSTRAINT ""polls_klassb_m2m_to_a_klassa_id_b63f26b4_fk_polls_klassa_id"" FOREIGN KEY (""klassa_id"") REFERENCES ""polls_klassa"" (""id"") DEFERRABLE INITIALLY DEFERRED;
CREATE INDEX ""polls_klassb_m2m_to_a_klassb_id_58ef37e1"" ON ""polls_klassb_m2m_to_a"" (""klassb_id"");
CREATE INDEX ""polls_klassb_m2m_to_a_klassa_id_b63f26b4"" ON ""polls_klassb_m2m_to_a"" (""klassa_id"");
COMMIT;
}}}

Here we get `CREATE TABLE ""polls_klassb_m2m_to_a"" (""id"" serial NOT NULL PRIMARY KEY...`

If we change in settings.py `DEFAULT_AUTO_FIELD` to `django.db.models.BigAutoField` we get `CREATE TABLE ""polls_klassb_m2m_to_a"" (""id"" bigserial NOT NULL PRIMARY KEY...`

I did a little bit of research and found out 2 probable causes affecting
Options::_get_default_pk_class:

1. When AppConfigStub is supplied instead of AppConfig it is stripped
from most of the properties including default_auto_field.
2. When the first migration for a given app is applied, we don't get
any app config as it is lazily registered in StateApps::register_models.
As this is the first model for this app, the config is no there yet.
"	Uncategorized	closed	Database layer (models, ORM)	3.2	Normal	duplicate	default_auto_field		Unreviewed	0	0	0	0	0	0
