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