typeddjango / django-stubs

PEP-484 stubs for Django
MIT License
1.61k stars 452 forks source link

Inheritance from models fields #285

Open AlwxSin opened 4 years ago

AlwxSin commented 4 years ago

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:

How can I annotate generic CharField?

And how can I pass kwargs to super?

youssefm commented 4 years ago

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 commented 4 years ago

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 commented 4 years ago

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 commented 4 years ago

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 commented 4 years ago

@sobolevn doesn't work, it results in:

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

That because of https://github.com/django/django/pull/12405

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

blueyed commented 2 years ago

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()
psasselum commented 8 months ago

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)