繁体   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