簡體   English   中英

使用模型方法作為Django Model的默認值?

[英]Use model method as default value for Django Model?

我實際上在我的模型中有這個方法:

def speed_score_compute(self):
  # Speed score:                                                                                                     
  #                                                                                                                  
  #   - 8 point for every % of time spent in                                                                         
  #     high intensity running phase.                                                                                
  #   - Average Speed in High Intensity                                                                              
  #     running phase (30km/h = 50 points                                                                            
  #     0-15km/h = 15 points )

  try:
    high_intensity_running_ratio = ((
      (self.h_i_run_time * 100)/self.training_length) * 8)
  except ZeroDivisionError:
    return 0
  high_intensity_running_ratio = min(50, high_intensity_running_ratio)
  if self.h_i_average_speed < 15:
    average_speed_score = 10
  else:
    average_speed_score = self.cross_multiplication(
      30, self.h_i_average_speed, 50)
  final_speed_score = high_intensity_running_ratio + average_speed_score
  return final_speed_score

我想將它用作我的模型的默認值,如下所示:

speed_score = models.IntegerField(default=speed_score_compute)

但這不起作用(請參閱下面的錯誤消息)。 我已經檢查過像這樣的不同主題,但這只適用於函數(不使用self屬性)而不適用於方法(我必須使用方法,因為我正在處理實際的對象屬性)。

Django doc。 似乎是在討論這個問題,但我並不清楚,因為我仍然是Django和Programmation的新手。

有沒有辦法實現這個目標?

編輯:

我的功能在我的模型上面定義。 但這是我的錯誤信息:

ValueError: Could not find function speed_score_compute in tournament.models. Please note that due to Python 2 limitations, you cannot serialize unbound method functions (eg a method declared and used in the same class body). Please move the function into the main module body to use migrations. For more information, see https://docs.djangoproject.com/en/1.8/topics/migrations/#serializing-values

錯誤信息很明顯,似乎我無法做到這一點。 但還有另一種方法來實現這一目標嗎?

問題

當我們提供default=callable並從模型中提供方法時,不會使用作​​為模型實例的self參數調用它。

覆蓋save()

我沒有找到比覆蓋MyModel.save() *更好的解決方案,如下所示:

class MyModel(models.Model):
    def save(self, *args, **kwargs):
        if self.speed_score is None:
            self.speed_score = ...
            # or
            self.calculate_speed_score()

        # Now we call the actual save method
        super(MyModel, self).save(*args, **kwargs)

這使得如果您嘗試保存模型而沒有該字段的設置值,則會在保存之前填充它。

我個人更喜歡這種方法,即擁有屬於模型的所有東西,在模型中定義(數據,方法,驗證,默認值等)。 我認為這種方法被稱為胖Django模型方法

*如果你找到更好的方法,我也想了解它!

使用pre_save信號

Django提供了一個pre_save信號,該信號在模型上運行save()之前運行。 信號同步運行,即pre_save代碼需要在模型上調用save()之前完成運行。 您將獲得與覆蓋save()相同的結果(以及執行順序save()

from django.db.models.signals import pre_save
from django.dispatch import receiver
from myapp.models import MyModel


@receiver(pre_save, sender=MyModel)
def my_handler(sender, **kwargs):
    instance = kwargs['instance']
    instance.populate_default_values()

如果您希望將默認值行為與模型分開,則此方法適合您!

什么時候調用save() 在保存之前我可以使用該對象嗎?

好問題! 因為我們希望能夠在保存填充默認值之前使用我們的對象。

要獲得一個對象,而不保存它,只需使用它我們就可以:

instance = MyModel()

如果使用MyModel.objects.create() 創建它,則將調用save() 它本質上(參見源代碼)等效於:

instance = MyModel()
instance.save()

如果它對您有意思,您還可以定義一個MyModel.populate_default_values() ,您可以在對象生命周期的任何階段調用(在創建時,保存時或on-demande,這取決於您)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM