#python #django #django-models #django-queryset
Вопрос:
Не уверен, что я нахожусь на совершенно неправильном пути, но мне нужна какая-то временная переменная/поле времени выполнения в моей модели Django. В настоящее время у меня есть это:
class BioChemicalProperties(models.Model):
mw = models.FloatField(blank=True, null=True)
iep = models.FloatField(blank=True, null=True)
exco = models.FloatField(blank=True, null=True)
molar_exco = models.FloatField(blank=True, null=True)
e01 = models.FloatField(blank=True, null=True)
def get_protein(self):
aa_seq = self.ab.get_lc_protein()
aa_seq = self.ab.get_hc_protein()
return aa_seq
def calc_mw(self, aa_seq=None):
if not aa_seq:
aa_seq = self.get_protein()
analysed_seq = ProteinAnalysis(aa_seq)
self.mw = analysed_seq.molecular_weight() 18.015
def calc_exco(self, aa_seq=None):
if not aa_seq:
aa_seq = self.get_protein()
analysed_seq = ProteinAnalysis(aa_seq)
self.exco = analysed_seq.molar_extinction_coefficient()[1]
#...more methods here...
def calc_all_bioprops(self, aa_seq=None):
if not aa_seq:
aa_seq = self.get_protein()
self.calc_mw(aa_seq)
self.calc_iep(aa_seq)
self.calc_molexco(aa_seq)
self.calc_e01(aa_seq)
aa_seq
Переменная является временным значением, которое не должно храниться в базе данных. Тем не менее, чтобы не пересчитывать значение для каждого метода при использовании нескольких методов, я хочу при необходимости указать его в качестве параметра. Я вижу, что указание параметра aa_seq
в качестве параметра в каждом методе является избыточным и также не объектно-ориентированным. Теперь я задаюсь вопросом, хорошо ли (и возможно ли вообще) хранить его как свойство класса, например:
class BioChemicalProperties(models.Model):
mw = models.FloatField(blank=True, null=True)
iep = models.FloatField(blank=True, null=True)
exco = models.FloatField(blank=True, null=True)
molar_exco = models.FloatField(blank=True, null=True)
e01 = models.FloatField(blank=True, null=True)
aa_seq = ""
def calc_mw(self):
if not self.aa_seq:
self.aa_seq = self.get_protein()
analysed_seq = ProteinAnalysis(self.aa_seq)
self.mw = analysed_seq.molecular_weight() 18.015
Однако я не нашел подобных примеров, в которых поля модели и немодельные поля были mixed…is для этого есть причина?
Ответ №1:
Ваша идея хороша, но ваша номенклатура запутана.
Нет абсолютно ничего плохого в том, чтобы сохранить его в качестве атрибута экземпляра. Это не поле, и то, что оно находится на модели, является случайным совпадением. Модели-это просто частные случаи классов.
Вот пример того, как атрибуты, не относящиеся к полю, определяются в Model
подклассе в самих документах Django.
Комментарии:
1. Спасибо вам за ваш ответ. Я реализовал его, и он действительно работает так, как ожидалось.
2. ИМО это действительно (я тоже проголосовал), но обычно атрибуты, не относящиеся к полю, используются для чего-то вроде констант (например, для выбора в примере). И при таком подходе можно было бы установить значение на что-то другое, вместо того, чтобы всегда быть уверенным, что это вычисляемое поле с использованием
property
илиcached_property
(без задатчика). Также не потребуется ли для этого постоянная проверка того, было ли рассчитано это значение, так что кучаif not self.aa_seq: self.aa_seq = calculate()
?3. @BrianD Я должен полностью с вами не согласиться. Примерами непостоянных вещей, которые я регулярно использую в качестве атрибутов, отличных от полей, являются экземпляры менеджера, экземпляры отслеживания полей, временные переменные, классы опций и так далее.
Ответ №2:
Похоже, что-то cached_property
может сделать:
from django.utils.functional import cached_property
class BioChemicalProperties(models.Model):
...
@cached_property
def aa_seq(self):
return self.ab.get_lc_protein() self.ab.get_hc_protein()
Затем вы можете просто использовать self.aa_seq
то, что у вас есть в настоящее время, и вы можете удалить if not aa_seq
проверки, так как они больше не нужны. Кроме того, это приведет к кэшированию вычисленного значения aa_seq
в течение всего срока службы экземпляра без сохранения чего-либо в БД.
Комментарии:
1. Привет @BrianD, спасибо за ваше предложение. Хотя первоначальный простой подход к использованию атрибута экземпляра, похоже, уже сделал свое дело, свойство cached_property было для меня новым, и это выглядит как интересный подход для других вариантов использования!
2. Все хорошо! Я поддержал ответ @Адама Барнса, но при таком подходе имейте в виду, что вам всегда придется проверять, был ли
aa_seq
он уже рассчитан (if not aa.seq
). Также можно было бы установить для него другое значение за пределами экземпляра, что потенциально может привести к поведению, которого вы не ожидаете (напримерinstance.aa_seq = somerandomvalue
). Но решать вам