在Django项目中,我有一个扩展Django用户模型的模块,类似于以下内容:
from django.contrib.auth.models import User
def __str__(self):
return "%s %s" % (self.first_name, self.last_name)
User.add_to_class('__str__', __str__)
我注意到这可行。但是,如果我尝试定义__getattr__
方法,如下所示:
def __getattr__(self, attr):
if self.user_profile:
return getattr(self.user_profile, attr)
else:
raise AttributeError(f"'{self.__class__.__name__}' has no attribute '{attr}'")
导入模块时出现以下错误:
(lucy-web-CVxkrCFK) bash-3.2$ python manage.py shell
Traceback (most recent call last):
File "manage.py", line 28, in <module>
execute_from_command_line(sys.argv)
File "/Users/kurtpeek/.local/share/virtualenvs/lucy-web-CVxkrCFK/lib/python3.7/site-packages/django/core/management/__init__.py", line 371, in execute_from_command_line
utility.execute()
File "/Users/kurtpeek/.local/share/virtualenvs/lucy-web-CVxkrCFK/lib/python3.7/site-packages/django/core/management/__init__.py", line 347, in execute
django.setup()
File "/Users/kurtpeek/.local/share/virtualenvs/lucy-web-CVxkrCFK/lib/python3.7/site-packages/django/__init__.py", line 24, in setup
apps.populate(settings.INSTALLED_APPS)
File "/Users/kurtpeek/.local/share/virtualenvs/lucy-web-CVxkrCFK/lib/python3.7/site-packages/django/apps/registry.py", line 112, in populate
app_config.import_models()
File "/Users/kurtpeek/.local/share/virtualenvs/lucy-web-CVxkrCFK/lib/python3.7/site-packages/django/apps/config.py", line 198, in import_models
self.models_module = import_module(models_module_name)
File "/Users/kurtpeek/.local/share/virtualenvs/lucy-web-CVxkrCFK/lib/python3.7/importlib/__init__.py", line 127, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
File "<frozen importlib._bootstrap>", line 983, in _find_and_load
File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 728, in exec_module
File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
File "/Users/kurtpeek/Documents/Dev/lucy2/lucy-web/lucy_web/models/__init__.py", line 25, in <module>
from .user import User
File "<frozen importlib._bootstrap>", line 1019, in _handle_fromlist
TypeError: __getattr__() missing 1 required positional argument: 'attr'
是否无法通过User
方法扩展__getattr__
模型?
答案 0 :(得分:1)
在python 3.7中,如果定义了名为__getattr__
it will be a module level attribute getter function的模块级函数,类似于类getattr。好像您是无意中那样。模块级别__getattr__
具有与类方法不同的调用签名。
规格
模块级别的
__getattr__
函数应 接受一个作为属性名称的参数,然后返回 计算值或引发AttributeError:def __getattr__(name: str) -> Any: ...
尝试将函数重命名为其他名称,以避免无意间隐藏保留的函数名称。
def user_getattr(self, attr):
...
User.add_to_class('__getattr__', user_getattr)
此PEP可能会破坏使用模块级别(全局)名称的代码
__getattr__
和__dir__
。 (但该语言参考明确保留了所有未记录的dunder名称,并允许“ 警告”)
And here's what the language reference says:
在任何情况下都不得使用
__*__
名称 明确记录在案的使用,如有损坏,恕不另行通知。
因此,您还应该重命名自定义的__str__
函数,以避免将来可能发生损坏。