﻿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
36754	Broken migration created when GeneratedField's expression references a foreign key that has been deferred to another initial migration file	Ou7law007	Ou7law007	"When the autodetector builds CreateModel operations, it defers related fields (FK/M2M) into separate AddField operations. However, GeneratedField expressions are evaluated before those deferred fields exist in the CreateModel operation, causing the generated expression to reference a non‑existent column name. This results in inconsistent or invalid initial migrations on new apps.


== This is not easy to reproduce

In a small Django project, the dependency graph between apps is small. When Django detects initial migrations, it produces a single 0001_initial file per app. And since all fields (including FK targets used inside GeneratedField expressions) are created in that one file, Django never attempts to evaluate a GeneratedField expression that references a relationship **that does not yet exist**.


== When the bug happens

In larger projects, Django may split initial migrations into multiple files (0001_initial, 0002_initial, sometimes 0003_initial, etc.).
When this happens:
- Django may place a GeneratedField into 0001_initial.
- Django may place the ForeignKey needed by the GeneratedField expression into 0002_initial.
- Django then tries to serialize the GeneratedField expression in 0001_initial, but the FK field it references does not yet exist.
- This results in the following error: {{{django.core.exceptions.FieldError: Cannot resolve keyword 'category_id' into field. Choices are: id, ... etc.}}} with {{{category_id}}} being a  foreign key to a model that hasn't been processed yet.

In other words, the bug only appears when Django generates an initial migration before creating the FK that a GeneratedField depends on.

Also, note that it only happens on **INITIAL** migrations, which makes it even harder to reproduce, because you need an existing large project that needs to initialize all its models' migrations for the first time.


== Example (if you copy paste into a small project, you **won't** be able to reproduce the issue, read above for why)

app_a:

{{{
class Category(models.Model):
    name = models.CharField(max_length=100)
}}}

app_b:

{{{
class Item(models.Model):
    category = models.ForeignKey(""A.Category"", on_delete=models.CASCADE)

    # Problematic GeneratedField referring to category_id
    somefield = models.GeneratedField(
        expression=Concat(
            F(""category_id""), # or just category_id, makes no difference, both are bugged
            Value(""-""),
            F(""id""),
        ),
        output_field=models.CharField(max_length=50),
        db_persist=True,
        unique=True,
    )
}}}

{{{
B/0001_initial.py   # creates Item without the category FK
B/0002_initial.py   # adds the category FK
}}}


== Workarounds

1. Manually merge migrations i.e. move the FK field (or other dependencies) from 0002_initial.py into 0001_initial.py to **ensure that all fields used by GeneratedField expressions are created together**.

2. Improt the user model inside the initial custom user migration!!!! (That's a werid one) This one is based on django cookiecutter which creates a {{{users}}} app with a custom user model. I noticed that importing that custom model inside the initial user migration file i.e. put {{{import myproject.users.models}}} inside {{{myproject/users/migrations/0001_initial.py}}}, which is the default for django-cookiecutter projects, that's why if you're using cookiecutter, you will not have this bug unless you delete all migration files after your project grows enough and then try to migrate from scratch, then you notice the only difference between the old and new initial migration files is this line {{{import myproject.users.models}}} which fixes the bug. I also noticed that other apps had up to 3 000x_initial.py files but once I added {{{import myproject.users.models}}}, they went down to just one for each app.

Briefly and as a summary, the issue is that if a generated field (`somefield` in the example above) has a reference to a foreign key (or any other related field) (`category_id` in the example above) **AND** django happens to create multiple 000x_initial.py migration files for that app (see 1) **AND** the foreign relation field is declared in a later file than the generated field, then the bug happens because django processes the generated field, but the field that is mentioned inside of it.

I'd also appreciate it, if someone can answer this question: Is it an expected behavior that importing {{{import myproject.users.models}}} i.e. the custom user model in the users' apps initial migration file i.e. in {{{myproject/userss/migrations/0001_initial.py}}} causes less initial migration files to be generated for each app? Is this normal? Because this is what seems to solve the issue (or make it not even an issue)

1. https://docs.djangoproject.com/en/5.2/topics/migrations/#:~:text=but%20in%20some%20cases%20of%20complex%20model%20interdependencies%20it%20may%20have%20two%20or%20more"	Bug	assigned	Migrations	5.0	Normal		autodetector GeneratedField		Accepted	1	0	0	1	0	0
