Django: Приведите связанное поле к типу QuerySet

Основываясь на официальной документации:

# Declare the ForeignKey with related_name
class Tag(models.Model):
    article = models.ForeignKey(
        Article,
        on_delete=models.CASCADE,
        related_name="tags"
    )
    name = models.CharField(max_length=255)

# Return all tags
Article.tags.all()

Мой линтер (django-pylint) не в состоянии напечатать его правильно: Article.tags is Any, я ожидал QuerySet[Tag].


Могу ли я объявить ссылку Article.tags в классе Article? (предпочтительный подход)

from django.db.models.query import QuerySet

class Article(models.Model):
    ...
    # Related field declaration
    tags: QuerySet[Tag]

Article.tags.all()

Или, может быть, мне нужно конвертировать его каждый раз, когда он мне нужен?

tags_qs: QuerySet[Tag] = Article.tags
tags_qs.all()

В обоих сценариях это выглядит тяжелым для реализации для каждой связанной области.


Конечно, это скорее вопрос для удобства разработки, чем критическая проблема. Цель состоит в том, чтобы позволить моему линтеру и другим инструментам автозаполнения/распознавания разрешать связанные поля как тип QuerySet[T]. Возможно, я не могу этого сделать из-за дизайна реализации Python, что больше похоже на проблему Django.

Есть ли другая альтернатива для решения этой проблемы?

Благодаря @Anentropic за указание правильного пути, я выбрал django-types. Эта библиотека легко интегрируется с VS Code и расширением PyLance (которое использует проверку типов PyRight, а не MyPY).

Установка с помощью VS Code

  1. Clone django-types
  2. Переименуйте django_stubs в django
  3. .
  4. Переместите его в ./typings/django в папку проекта

Адаптация

Следуя этим инструкциям: https://github.com/sbdchd/django-types#usage

from __future__ import annotations  # or just be in python 3.11

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from django.db.models import Manager

class Article(models.Model):
    tags: Manager["Tag"]

# Declare the ForeignKey with related_name
class Tag(models.Model):
    article = models.ForeignKey(
        Article,
        on_delete=models.CASCADE,
        related_name="tags"
    )
    name = models.CharField(max_length=255)

# Return all tags
Article.tags.all()

Теперь PyLance работает нормально с автозаполнением!

Вернуться на верх