Skip to content

djangorestframework-stubs: ModelSerializer.Meta class pattern causes false positive bad-override errors #4595

Description

@dhitalkamal

Description

pyrefly reports bad-override errors for DRF's (Django REST Framework) ModelSerializer.Meta class pattern. This is a false positive - like marshmallow's Schema.Meta (see #2054, which was fixed), DRF's Meta is a configuration class pattern, not a true inheritance override.

Reproduction

from rest_framework import serializers
from django.db import models


class MyModel(models.Model):
    name = models.CharField(max_length=100)


class MySerializer(serializers.ModelSerializer):
    class Meta:
        model = MyModel
        fields = ["name"]

Requires django-stubs and djangorestframework-stubs installed (pyrefly's built-in Django support reads them directly, no mypy plugin involved).

Actual behavior

ERROR Class member `MySerializer.Meta` overrides parent class `ModelSerializer` in an inconsistent manner [bad-override]
    |
    |     class Meta:
    |           ^^^^
    |
  `MySerializer.Meta` has type `type[MySerializer.Meta]`, which is not assignable to `type[ModelSerializer.Meta]`, the type of `ModelSerializer.Meta`

Expected behavior

No error - this is the single most common way to write a DRF ModelSerializer (every DRF tutorial and the official docs use exactly this pattern).

Why this is a false positive

Same root cause as #2054: DRF's own ModelSerializer.Meta inner class is not something a concrete serializer is meant to inherit from. Confirmed at runtime:

>>> from rest_framework import serializers
>>> hasattr(serializers.ModelSerializer, "Meta")
False

ModelSerializer.Meta only exists in djangorestframework-stubs' .pyi file - not in the real, running rest_framework package. Writing class Meta(serializers.ModelSerializer.Meta): to "properly" inherit therefore crashes at import time with AttributeError: type object 'ModelSerializer' has no attribute 'Meta' - it's not a safe workaround, just a way to trade a type error for a runtime error.

The stubs also declare a generic ModelSerializer[_MT] with Meta.model: ClassVar[type[_MT]], so even parameterizing the generic and annotating model: ClassVar[type[MyModel]] = MyModel explicitly on a non-inheriting Meta still fails the same check (tested on pyrefly 1.2.0).

Real-world impact

This affects effectively every DRF ModelSerializer in any typed Django+DRF codebase - i.e. every project that installs djangorestframework-stubs for pyrefly to get real ORM/serializer typing at all.

Workaround

Can suppress with bad-override = "ignore" in [tool.pyrefly.errors], but that hides real override bugs elsewhere in the codebase, which isn't an acceptable tradeoff for us.

Environment

  • pyrefly version: 1.2.0
  • djangorestframework-stubs version: 3.18.0
  • django-stubs version: 6.1.0
  • Python: 3.14

Related

Metadata

Metadata

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions