﻿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
33174	Having a model inherit from Generic[T] breaks makemigrations	Antoine Humeau	Thibaut Decombe	"Here is a simple example that can help me explain the issue (and maybe show you why this might be a valid usecase):
{{{
#!python
import typing
from django.db import models
import stripe
from stripe.stripe_object import StripeObject


StripeClassT = typing.TypeVar('StripeClassT', bound=StripeObject)


class StripeObjectModel(typing.Generic[StripeClassT], models.Model):
    stripe_class: type[StripeClassT]

    id = models.TextField(primary_key=True)

    class Meta:
        abstract = True

    def api_retrieve(self) -> StripeClassT:
        return self.stripe_class.retrieve(self.id)
   

class Customer(StripeObjectModel):
    stripe_class = stripe.Customer


class Source(StripeObjectModel):
    stripe_class = stripe.Source
...
}}}

Running `makemigrations` will result in the following traceback: 
{{{
Traceback (most recent call last):
  File ""...django/core/management/__init__.py"", line 419, in execute_from_command_line
    utility.execute()
  File ""...django/core/management/__init__.py"", line 413, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File ""...django/core/management/base.py"", line 354, in run_from_argv
    self.execute(*args, **cmd_options)
  File ""...django/core/management/base.py"", line 398, in execute
    output = self.handle(*args, **options)
  File ""...django/core/management/base.py"", line 89, in wrapped
    res = handle_func(*args, **kwargs)
  File ""...django/core/management/commands/makemigrations.py"", line 172, in handle
    changes = autodetector.changes(
  File ""...django/db/migrations/autodetector.py"", line 41, in changes
    changes = self._detect_changes(convert_apps, graph)
  File ""...django/db/migrations/autodetector.py"", line 127, in _detect_changes
    self.new_apps = self.to_state.apps
  File ""...django/utils/functional.py"", line 48, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File ""...django/db/migrations/state.py"", line 208, in apps
    return StateApps(self.real_apps, self.models)
  File ""...django/db/migrations/state.py"", line 270, in __init__
    self.render_multiple([*models.values(), *self.real_models])
  File ""...django/db/migrations/state.py"", line 305, in render_multiple
    model.render(self)
  File ""...django/db/migrations/state.py"", line 572, in render
    return type(self.name, bases, body)
  File ""...django/db/models/base.py"", line 99, in __new__
    new_class = super_new(cls, name, bases, new_attrs, **kwargs)
  File ""/usr/lib/python3.9/typing.py"", line 1010, in __init_subclass__
    raise TypeError(""Cannot inherit from plain Generic"")
TypeError: Cannot inherit from plain Generic

}}}

I have tracked down the issue to the following chain of events:
- [https://github.com/django/django/blob/4540e976d4e941166fbd2d3f1df1853f7e348740/django/db/migrations/state.py#L396 ModelState.from_model] is called with `Customer` as argument
- It recursively builds a list of base classes for `Customer` from `Customer.__bases__` and uses it to return a `ModelState` instance
- This base class list will contain `typing.Generic` – note: not `typing.Generic[StripeClassT]` – because it is present in `StripeObjectModel.__bases__`
- The `ModelState` instance's [https://github.com/django/django/blob/4540e976d4e941166fbd2d3f1df1853f7e348740/django/db/migrations/state.py#L551 render] method gets called
- An exception is raised in when calling `type(self.name, bases, body)` because subclassing unparameterized `typing.Generic` is not allowed

A simple solution might be to filter out `typing.Generic` from `bases` in `ModelState.from_model`."	Bug	closed	Migrations	3.2	Normal	fixed		Adam Johnson Alexandr Artemyev HarryKane elonzh	Ready for checkin	1	0	0	0	0	0
