如何让Django、类型注解、Flake8协同工作?
How to make Django, type annotations, and Flake8 work together?
我正在使用 Django/DRF。我想写类型检查 Python。我也想要linting。
Django 的模型结构包括为每个模型创建一个管理器 class,并将管理器 class 的实例分配给模型的 objects
成员。
由于我使用的是类型注释,因此管理器 class 的方法现在还包含对模型的引用。这导致 flake8 报告一个或另一个错误。
这是一个例子:
class UserManager:
def create_user(email: str) -> User:
... ^^^^ [flake8] F821: undefined name 'User'
class User:
objects = UserManager()
如果我翻转它们,我会得到:
class User:
objects = UserManager()
^^^^^^^^^^^ [flake8] F821: undefined name 'UserManager'
class UserManager:
def create_user(email: str) -> User:
...
人们如何编写类型化、linted 的 Django 代码?
除了打字之外请注意:Django 的模型不要求您为每个模型都有一个明确的管理器! Django 在每个模型上使用 objects
属性 生成一个管理器。您只需要为特定用途添加自定义 ModelManager。转到类型...
我认为如果您实际使用 UserManager,您应该将它放在 User 之前 class。对于尚未定义的名称,您可以将类型用引号引起来,PEP 484 under the "Forward References" section 的文档中对此进行了介绍。
class UserManager:
def create_user(email: str) -> "User":
...
class User:
objects = UserManager()
另一种选择是在注释中使用 Python 2 语法定义类型提示, 显示了类似的答案。
class UserManager:
def create_user(email: str):
# type: (str) -> User
...
在 Python 3.7 中,您可以使用 from __future__ import annotations
修复此问题,这将允许包含前向引用的类型注释。对于更简单的代码重构和 linting,这比使用字符串注释(如另一个答案所建议的)更可取。使用引号只是不支持前向引用注释的 Python 旧版本的解决方法。在 Python 4(如果不是更早的话)中,这将是默认行为。
我正在使用 Django/DRF。我想写类型检查 Python。我也想要linting。
Django 的模型结构包括为每个模型创建一个管理器 class,并将管理器 class 的实例分配给模型的 objects
成员。
由于我使用的是类型注释,因此管理器 class 的方法现在还包含对模型的引用。这导致 flake8 报告一个或另一个错误。
这是一个例子:
class UserManager:
def create_user(email: str) -> User:
... ^^^^ [flake8] F821: undefined name 'User'
class User:
objects = UserManager()
如果我翻转它们,我会得到:
class User:
objects = UserManager()
^^^^^^^^^^^ [flake8] F821: undefined name 'UserManager'
class UserManager:
def create_user(email: str) -> User:
...
人们如何编写类型化、linted 的 Django 代码?
除了打字之外请注意:Django 的模型不要求您为每个模型都有一个明确的管理器! Django 在每个模型上使用 objects
属性 生成一个管理器。您只需要为特定用途添加自定义 ModelManager。转到类型...
我认为如果您实际使用 UserManager,您应该将它放在 User 之前 class。对于尚未定义的名称,您可以将类型用引号引起来,PEP 484 under the "Forward References" section 的文档中对此进行了介绍。
class UserManager:
def create_user(email: str) -> "User":
...
class User:
objects = UserManager()
另一种选择是在注释中使用 Python 2 语法定义类型提示,
class UserManager:
def create_user(email: str):
# type: (str) -> User
...
在 Python 3.7 中,您可以使用 from __future__ import annotations
修复此问题,这将允许包含前向引用的类型注释。对于更简单的代码重构和 linting,这比使用字符串注释(如另一个答案所建议的)更可取。使用引号只是不支持前向引用注释的 Python 旧版本的解决方法。在 Python 4(如果不是更早的话)中,这将是默认行为。