如何使Django,类型注释和Flake8协同工作?

时间:2018-09-07 00:34:58

标签: django types django-rest-framework python-3.7 flake8

我正在使用Django / DRF。我想编写经过类型检查的Python。我也想要绒毛。

Django的模型结构包括为每个模型创建一个管理器类,并将管理器类的实例分配给模型的objects成员。

由于我使用的是类型注释,所以经理类的方法现在还包括对模型的引用。这会导致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:
        ...                        

人们如何编写带类型的,倾斜的Django代码?

2 个答案:

答案 0 :(得分:2)

除键入内容外,请注意:Django的模型不需要,您需要为每个模型都拥有一个明确的管理器! Django在每个模型上使用objects属性生成一个Manager。您只需要添加定制的ModelManager即可用于特定用途。进入类型...

如果您实际上正在使用该类,我认为应该将UserManager放在User之前。您可以将类型包装在引号中以表示尚未定义的名称,PEP 484 under the "Forward References" section的文档对此进行了介绍。

class UserManager:

    def create_user(email: str) -> "User":
        ...                        

class User:

    objects = UserManager()

另一种选择是在注释中使用Python 2语法定义类型提示,Type hinting in Python 2显示类似的答案。

class UserManager:

    def create_user(email: str):
        # type: (str) -> User
        ...

答案 1 :(得分:2)

在Python 3.7中,您可以使用from __future__ import annotations来解决此问题,这将允许类型注释包含正向引用。与使用字符串注释(如另一个答案所建议的)相比,此方法更可取,以简化代码重构和插入。对于不支持前向引用注释的旧版Python,使用引号只是一种解决方法。在Python 4中(如果不是更早的话),这将是默认行为。