我们有一个Django
项目,今年我多次遇到此问题。
我将简化示例:
class MyModel(Model):
my_attr = ....
...
def get_my_attr_safe():
if not self.my_attr:
return somecalculation()
return self.my_attr
我想强迫开发人员使用get_my_attr_safe()
而不是my_attr
。
这是一个庞大而复杂的模型。
我的想法是以某种方式覆盖__getattribute__
并引发Exception,如果直接调用它,但我认为这不起作用。而且,Django
当然有时需要直接调用ModelFields
,所以我不能只是这样做。
我想举起Exception
或确保他们将获得尽可能使用method
的信息。
例如,我需要他们在模板中的任何地方使用该方法:
{{ obj.get_my_attr_safe }}
代替
{{ obj.my_attr }}
解决方案不一定是Python
ic,也许有一种方法可以只使用PyCharm
来实现。足够了。
答案 0 :(得分:2)
以下划线的使用可能会有所帮助:
class MyModel(Model):
_my_attr = None
def get_my_attr_safe(self):
if self._my_attr is None:
self._my_attr = somecalculation()
return self._my_attr
my_attr = property(get_my_attr_safe)
答案 1 :(得分:0)
我不建议覆盖__getattr__
或触摸Model
类中的任何内容。这是Django的核心,如果您执行某些操作,则可能不知道下一个错误将在哪里弹出。与其相比,我认为最好在其周围使用包装器以获取限制。例如:
class YourModelWrapper(object):
model_object = None
restricted_fields = ['some', 'fields']
def __init__(self, model_object):
self.model_object = model_object
def __getattr__(self, name):
if name is not in self.restricted_fields:
return getattr(self.model_object, name)
raise AttributeError("Use get_{}_safe() method instead".format(name)
# Usage
your_model_wrapper_obj = YourModelWrapper(YourModel.objects.first())
your_model_wrapper_obj.my_attr # will raise exception
your_model_wrapper_obj.get_my_attr_safe() # will return the values
仅供参考,使用它而不是实际模型将很麻烦,因为该包装器缺少很多东西,例如查询集支持。但是也有一个好的方面。您已经说过您的模型非常复杂,因此使用包装器可能有助于将某些复杂性从模型放入包装器,或者像服务一样使用。