1
0
mirror of https://github.com/django/django.git synced 2025-06-13 07:29:13 +00:00

Fixed #33174 -- Fixed migrations crash for model inheriting from Generic[T].

This commit is contained in:
Thibaut Decombe 2025-04-26 17:02:57 +02:00 committed by Sarah Boyce
parent 8be0c0d690
commit 825ddda26a
7 changed files with 117 additions and 0 deletions

View File

@ -1,4 +1,5 @@
import copy
import typing
from collections import defaultdict
from contextlib import contextmanager
from functools import partial
@ -969,6 +970,7 @@ class ModelState:
bases = tuple(
(apps.get_model(base) if isinstance(base, str) else base)
for base in self.bases
if base != typing.Generic
)
except LookupError:
raise InvalidBasesError(

View File

@ -0,0 +1,40 @@
import typing
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
operations = [
migrations.CreateModel(
name="GenericModel",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
],
bases=(typing.Generic, models.Model),
),
migrations.CreateModel(
name="GenericModelPEP695",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
],
bases=(models.Model, typing.Generic),
),
]

View File

@ -0,0 +1,31 @@
from django.db import migrations, models
from ..models import Child
class Migration(migrations.Migration):
dependencies = [
("with_generic_model", "0001_initial"),
]
operations = [
migrations.CreateModel(
name="CustomGenericModel",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
],
bases=(
Child,
models.Model,
),
),
]

View File

@ -0,0 +1,36 @@
import typing
from django.db import models
T = typing.TypeVar("T")
class GenericModel(typing.Generic[T], models.Model):
"""A model inheriting from typing.Generic."""
class GenericModelPEP695[T](models.Model):
"""A model inheriting from typing.Generic via the PEP 695 syntax."""
# Example from Python docs:
# https://typing.python.org/en/latest/spec/generics.html#arbitrary-generic-types-as-base-classes
T1 = typing.TypeVar("T1")
T2 = typing.TypeVar("T2")
T3 = typing.TypeVar("T3")
class Parent1(typing.Generic[T1, T2]):
pass
class Parent2(typing.Generic[T1, T2]):
pass
class Child(Parent1[T1, T3], Parent2[T2, T3]):
pass
class CustomGenericModel(Child[T1, T3, T2], models.Model):
"""A model inheriting from a custom subclass of typing.Generic."""

View File

@ -1551,6 +1551,14 @@ class MigrateTests(MigrationTestBase):
recorder.record_unapplied("migrations2", "0002_second")
recorder.record_unapplied("migrations2", "0001_squashed_0002")
@override_settings(
INSTALLED_APPS=[
"migrations.migrations_test_apps.with_generic_model",
]
)
def test_migrate_model_inherit_generic(self):
call_command("migrate", verbosity=0)
class MakeMigrationsTests(MigrationTestBase):
"""