mirror of
https://github.com/django/django.git
synced 2025-06-14 16:09:12 +00:00
Fixed #33174 -- Fixed migrations crash for model inheriting from Generic[T].
This commit is contained in:
parent
8be0c0d690
commit
825ddda26a
@ -1,4 +1,5 @@
|
|||||||
import copy
|
import copy
|
||||||
|
import typing
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
from functools import partial
|
from functools import partial
|
||||||
@ -969,6 +970,7 @@ class ModelState:
|
|||||||
bases = tuple(
|
bases = tuple(
|
||||||
(apps.get_model(base) if isinstance(base, str) else base)
|
(apps.get_model(base) if isinstance(base, str) else base)
|
||||||
for base in self.bases
|
for base in self.bases
|
||||||
|
if base != typing.Generic
|
||||||
)
|
)
|
||||||
except LookupError:
|
except LookupError:
|
||||||
raise InvalidBasesError(
|
raise InvalidBasesError(
|
||||||
|
@ -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),
|
||||||
|
),
|
||||||
|
]
|
@ -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,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
@ -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."""
|
@ -1551,6 +1551,14 @@ class MigrateTests(MigrationTestBase):
|
|||||||
recorder.record_unapplied("migrations2", "0002_second")
|
recorder.record_unapplied("migrations2", "0002_second")
|
||||||
recorder.record_unapplied("migrations2", "0001_squashed_0002")
|
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):
|
class MakeMigrationsTests(MigrationTestBase):
|
||||||
"""
|
"""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user