Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inheritance from models fields #285

Open
AlwxSin opened this issue Dec 20, 2019 · 8 comments
Open

Inheritance from models fields #285

AlwxSin opened this issue Dec 20, 2019 · 8 comments

Comments

@AlwxSin
Copy link

AlwxSin commented Dec 20, 2019

I've got the following snippet

from django.db import models

class PhoneField(models.CharField):
    """Phone field based on CharField with validation."""

    def __init__(self, *args, **kwargs) -> None:
        """Init."""
        options = {
            "max_length": 30,
            "validators": (must_be_valid_number, ),
        }
        options.update(kwargs)
        super().__init__(*args, **options)

And there are two problems:

  • First - models.py:3 error: Missing type parameters for generic type "CharField"

  • And second

models.py:13: error: Argument 2 to "__init__" of "CharField" has incompatible type "**Dict[str, object]"; expected "Union[str, bytes, None]"
models.py:13: error: Argument 2 to "__init__" of "CharField" has incompatible type "**Dict[str, object]"; expected "Optional[str]"
models.py:13: error: Argument 2 to "__init__" of "CharField" has incompatible type "**Dict[str, object]"; expected "bool"
models.py:13: error: Argument 2 to "__init__" of "CharField" has incompatible type "**Dict[str, object]"; expected "Optional[int]"
models.py:13: error: Argument 2 to "__init__" of "CharField" has incompatible type "**Dict[str, object]"; expected "Optional[Iterable[Union[Tuple[Any, Any], Tuple[str, Iterable[Tuple[Any, Any]]]]]]"
models.py:13: error: Argument 2 to "__init__" of "CharField" has incompatible type "**Dict[str, object]"; expected "str"
models.py:13: error: Argument 2 to "__init__" of "CharField" has incompatible type "**Dict[str, object]"; expected "Iterable[Callable[..., None]]"
models.py:13: error: Argument 2 to "__init__" of "CharField" has incompatible type "**Dict[str, object]"; expected "Optional[Dict[str, Any]]"

How can I annotate generic CharField?

And how can I pass kwargs to super?

@youssefm
Copy link
Contributor

youssefm commented Dec 20, 2019

Can you try completing the annotation on your init definition?

def __init__(self, *args: Any, **kwargs: Any) -> None:

and type your options variable:

options: Dict[str, Any] = {

@AlwxSin
Copy link
Author

AlwxSin commented Dec 22, 2019

I did and incompatible type "**Dict[str, object]" errors are gone.

But I still get models.py:3 error: Missing type parameters for generic type "CharField" error.

@layoaster
Copy link

I also have the same error: Missing type parameters for generic type "DateTimeField" when subclassing a Django DateTime field.

class AutoDateTimeField(models.DateTimeField):
    """
    A custom model field based on :class:`django.db.models.DateTimeField` that
    updates itself to `django.utils.timezone.now()` upon updating it's model.
    """

    def pre_save(self, model_instance, add) -> datetime:
        """
        Hook to timestamp model before it's saved.
        """
        return timezone.now()

Any workaround?

@sobolevn
Copy link
Member

All fields are generic with kind of 2: https://github.com/typeddjango/django-stubs/blob/master/django-stubs/db/models/fields/__init__.pyi#L45

You can try to do something like this:

from typing import TypeVar

# __set__ value type
_ST = TypeVar("_ST")
# __get__ return type
_GT = TypeVar("_GT")

class AutoDateTimeField(models.DateTimeField[_ST, _GT]):
    ...

@layoaster
Copy link

@sobolevn doesn't work, it results in:

    class AutoDateTimeField(models.DateTimeField[_ST, _GT]):
TypeError: 'type' object is not subscriptable

@sobolevn
Copy link
Member

That because of django/django#12405

Sadly, I don't have any ideas on how to fix it except # type: ignore

@blueyed
Copy link
Contributor

blueyed commented Dec 7, 2021

That because of django/django#12405

Sadly, I don't have any ideas on how to fix it except # type: ignore

Just for reference: this can be fixed now with django_stubs_ext:

import django_stubs_ext

django_stubs_ext.monkeypatch()

dato added a commit to dato/bookwyrm that referenced this issue Oct 24, 2023
The three "ignore" directives are:

  - avoid unreadable boilerplate from inherited `Field` methods; and:
  - typeddjango/django-stubs#285 (comment)
@psasselum
Copy link

I encountered this error because I was typing something that was already implicitly typed correctly:

-     name: models.CharField = models.CharField(max_length=100, primary_key=True)
+     name = models.CharField(max_length=100, primary_key=True)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

6 participants