Как заставить / предупредить, как разработчики относятся к модели класса / django - PullRequest
0 голосов
/ 21 ноября 2018

У нас есть проект 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 }}

Решение не должно быть Pythonic, может быть, есть способ сделать это, используя только PyCharm.Этого было бы достаточно.

Ответы [ 2 ]

0 голосов
/ 21 ноября 2018

Я бы не рекомендовал переопределять __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

FYI будет неудобно использовать это вместо фактической модели, потому что в этой оболочке много чего не хватает, например, поддержка набора запросов.Но есть и хорошая сторона.Вы сказали, что ваша модель очень сложная, поэтому использование оболочки может помочь перенести некоторые сложности из Model в Wrapper или использовать ее как сервис.

0 голосов
/ 21 ноября 2018

Здесь может помочь использование подчеркивания:

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)

Взято из этого ответа

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...