Which one is the correct way of using Python type hints with Django Models?

Question:

Which one of these is the correct way to use type annotations for django models?

from typing import TypeVar, Generic
from app.models import User

_T = TypeVar("_T", bound=User)

def func(user: Generic[_T]):
    user.name = 'John'
    user.save()

Or

from typing import Type
from app.models import User

def func(user: Type(User)):
    user.name = 'John'
    user.save()

Or

from app.models import User

def func(user: User):
    user.name = 'John'
    user.save()
Asked By: scaryhamid

||

Answers:

If arg should be a MyModel object, then you use:

from app.models import User


def func(arg: User):
    user.name = 'John'
    user.save()

or you can avoid importing the MyModel if you do not need to work with it with:

from typing import TYPE_CHECKING
from __future__ import annotations

if TYPE_CHECKING:
    from app.models import User


def func(arg: 'User'):
    user.name = 'John'
    user.save()

since importing only for type hints can easily result in cyclic import errors.

These will also accept subclasses, so if MyModel is for example an abstract base model, then submodels are also valid for the type hints.

Using Generic itself makes not much sense: this is used to define a specific type hint itself, for example a Dict. Furthermore Type(MyModel) means that you would pass the type itself, which is a subclass of MyModel, this thus means that you pass a reference to the MyModel class for example, not a MyModel object.

Answered By: Willem Van Onsem