简体   繁体   中英

Django: Resolve a related field to QuerySet type

Based on the official documentation:

# 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()

My linter (django-pylint) is unable to type it porperly: Article.tags is Any , I expected a QuerySet[Tag] .


Can I declare the Article.tags reference in the Article class? (preferred approach)

from django.db.models.query import QuerySet

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

Article.tags.all()

Or maybe I need to convert it every time I need it?

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

In both scenarios, it looks heavy to implement for each related field.


Of course, it's more a question for comfortable development experience than a critical issue. The goal is to allow my linter and other autocompletion/discovery tools to resolve related fields as QuerySet[T] type. Maybe I can't due to the design of the Python implementation, more than a Django issue.

Is there any other alternative to fix this problem?

Thanks to @Anentropic for pointing me in the right way, I opted for django-types . This library can be easily integrated with VS Code and the PyLance extension (which uses PyRight type checking, not MyPY).

Setup with VS Code

  1. Clone django-types
  2. Rename django_stubs to django
  3. Move it into ./typings/django in your project folder

Adaptation

Following this instructions: 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()

Now, PyLance working fine with autocompletion!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM