Поиск лучших практик для запросов 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(). Вы также можете кэшировать результаты такого запроса