mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Fixed #33174 -- Fixed migrations crash for model inheriting from Generic[T].
This commit is contained in:
		
				
					committed by
					
						 Sarah Boyce
						Sarah Boyce
					
				
			
			
				
	
			
			
			
						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): | ||||||
|     """ |     """ | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user