Поиск лучших практик для запросов Django в классах Python

Допустим, у меня есть модель Django Model1 и есть класс python Class1. Class1 имеет некоторые свойства, которые являются производными от значений в Model1. Каков наилучший способ решить эту задачу? Получить доступ к Mode1 в методе Class1 __init__ или получить доступ к Model1 в свойстве Class1? Не уверен, как определить "лучший способ" - более питонический, более эффективный и т.д.?

Очень надуманный пример того, о чем я спрашиваю:

class Model1(models.Model):
    model_id = models.AutoField(primary_key=True)
    field1 = models.CharField()
    field2 = models.CharField()

class Class1:
    def __init__(self, value1, value2):
        self.value1 = value1
        self.value2 = value2
        self._model1 = Model.objects.get(model_id=self.value1)

    @property
    def value3(self):
        return self._model1.field1 * 10

    @property
    def value4(self):
        field2 = Model.objects.get(model_id=self.value2).field2
        return field2 * 22

Какая парадигма "лучше" - свойство для value4 или value3?

Я предполагаю, что свойство для value4 более эффективно, потому что набор запросов Model1 не болтается в памяти, как это происходит, когда он содержится в Class1 __init__.

Спасибо!

Совсем не очевидно, зачем нужен Class1. Для многих (не всех) целей можно определить методы/свойства на классе Model1. (См. также Django proxy models)

В противном случае __init__ получить _model1, если этот экземпляр будет использоваться всегда и если он должен сохраняться так же долго, как и экземпляр Class1. Получать из БД по мере необходимости в свойстве Class1, если это свойство или эти свойства не всегда будут использоваться, или если актуальные значения из БД требуются каждый раз, когда вызывается значение свойства.

Также можно сделать _model свойством, которое запрашивает БД для получения и кэширования, скажем, self._model_instance. Таким образом, вы получите лучшее из двух вышеперечисленных вариантов (но, возможно, будет сложнее отлаживать, если get не сработает).

@property
def _model1( self):
    if not hasattr( self, '_model1_instance'):
        self._model1_instance = Model.objects.get(model_id=self.value1)
    return self._model1_instance

Избежание ненужных обращений к БД обычно является гораздо более существенным преимуществом, чем любые тонкости кодирования на Python.

Выигрыш в эффективности будет меньше, если вы не будете создавать весь экземпляр модели, а получите из БД только интересующие вас поля. См. Django queryset .values() и .values_list(). Вы также можете кэшировать результаты такого запроса

Вернуться на верх