Django模型的类型注解

xqk2d5yq  于 2022-12-05  发布在  Go
关注(0)|答案(1)|浏览(162)

我正在做一个Django项目。因为这是一个新项目,我想用python 3.6+类型注解来完全注解它。我正在尝试注解模型,但是我很难找到一个好的方法。
让我们以IntegerField为例,我看到有两种注解选择:

# number 1
int_field: int = models.IntegerField()

# number 2
int_field: models.IntegerField = models.IntegerField()

第1个失败于mypy:

Incompatible types in assignment (expression has type "IntegerField[<nothing>, <nothing>]", variable has type "int")

第2个问题对于mypy来说是可以的,但是作为PyCharm的IDE无法解决这个问题,并且经常抱怨使用了错误的类型。
是否有任何最佳实践来正确注解模型,这将满足我和IDE的?

wi3ka0sx

wi3ka0sx1#

Django模型(和其他组件)很难注解,因为它们背后有很多魔法,好消息是一群 * 很酷的开发者 * 已经为我们做了艰苦的工作。
django-stubs提供了一组stub和mypy插件,为Django提供静态类型和类型推断。
例如,具有以下模型:

from django.contrib.auth import get_user_model
from django.db import models

User = get_user_model()

class Post(models.Model):
    title = models.CharField(max_length=255)
    pubdate = models.DateTimeField()
    author = models.ForeignKey(User, on_delete=models.CASCADE)

mypy会抱怨说:

demo$ mypy .
demo/models.py:9: error: Need type annotation for 'title'
demo/models.py:10: error: Need type annotation for 'pubdate'
demo/models.py:11: error: Need type annotation for 'author'
Found 3 errors in 1 file (checked 5 source files)

要修复它,只需安装软件包

pip install django-stubs

并使用以下内容创建一个setup.cfg文件:

[mypy]
mypy_path = ./demo
plugins =
    mypy_django_plugin.main

strict_optional = True

[mypy.plugins.django-stubs]
django_settings_module = demo.settings
  • (不要忘记更新mypy_pathdjango_settings_module以指向您的设置模块的目录,这取决于您的设置模块的命名方式)*

完成后,mypy将能够推断和检查Django模型(和其他组件)的注解。

demo$ mypy .
Success: no issues found in 5 source files

下面是一个小视图中的用法示例:

from django.db.models.query import QuerySet
from django.http import HttpRequest, HttpResponse
from django.shortcuts import render

from demo.models import Post

def _get_posts() -> 'QuerySet[Post]':
    return Post.objects.all()

def posts(request: HttpRequest, template: str='posts.html') -> HttpResponse:
    return render(request, template, {'posts': _get_posts()})

同样,mypy对提供的注解很满意:

demo$ mypy .
Success: no issues found in 7 source files

同样的,Django Rest Framework的一个包也是可用的:是的。

相关问题