Skip to main content
 首页 » 编程设计

python之Django之改变一对多关系中相关对象的值

2024年08月23日32think

我有一个代表财务模型的 Django 模型。此模型与另一组也包含财务数据的模型具有一对多关系。在我的数据库中,我以美元($)存储值,但是当我开始使用模型时,我希望能够在欧元和英镑之间进行转换。

因此,我在我的模型中添加了一个名为 convert_to_ccy(rate) 的方法,如果我调用它,我希望它也转换相关模型(通过这种一对多关系)。这是一个非常简单的示例来说明我正在尝试做的事情。

class main_model_example(models.Model): 
 
    INCLUDE_IN_CCY_CONVERSION = ['value_field_1', 'value_field_2' etc...] 
 
    # FIELD DEFINITIONS 
    date = models.DateField() 
    value_field_1 = models.DecimalField(max_digits=20, decimal_places=2, default=0.00) 
    value_field_2 = models.DecimalField(max_digits=20, decimal_places=2, default=0.00) 
    ...etc... 
 
    # METHODS 
    def convert_to_ccy(self, rate): 
    """Converts $ fields""" 
        for field in self._meta.get_all_field_names(): 
            if field in self.INCLUDE_IN_CCY_CONVERSION: 
                value = getattr(self, field) 
                    if value != None: 
                    setattr(self, field, float(value) / rate) 
 
        # NOW CONVERT THE RELATED MODELS 
        for position in self.the_related_model_set.all(): 
            position.convert_to_ccy_rate(rate) 
 
 
# THE RELATED MODEL 
class the_related_model(models.Model): 
 
    INCLUDE_CCY_CONVERSION = ['yet_another_finacial_field'] 
 
    main_model_example = models.ForeignKey(main_model_example, on_delete=models.CASCADE) 
    yet_another_financial_field = models.DecimalField(max_digits=20, decimal_places=2, default=0.00) 
    ...and so on.... 
 
    def convert_to_ccy(self, rate): 
    """Converts $ fields""" 
        for field in self._meta.get_all_field_names(): 
            if field in self.INCLUDE_IN_CCY_CONVERSION: 
                value = getattr(self, field) 
                    if value != None: 
                    setattr(self, field, float(value) / rate) 

这有效,并转换了正确的字段。在我的代码(views.py 等)中,我传递了主要模型,它保留了我设置的新值(即以欧元为单位)。

但是,当我再次从相关模型中获取信息时(通过使用 model.the_related_model_set.all() 的主模型,值又恢复为美元。我认为这是因为 xxx_set.all() 方法再次从数据库中检索模型(尚未更新)。我想要的是一旦我更新了相关模型,让它们保留在内存中,这样当我再次使用它们时保留我设置的更新值.我已经阅读了文档并浏览了问题,但似乎找不到任何类似的内容。

所以我有两个问题:

  1. 我想要实现的目标是可能的吗?即更新内存中的相关(一对多)模型,传递主模型(进行更多计算),然后在我稍后再次引用相关模型时取回更新后的值。

或者我是否需要在偏移量处从主模型中获取所有相关模型并将它们分配给一个我必须与主模型一起传递的变量?

  1. 我这样做是否被认为是不好的? IE。让主要模型方法调用相关模型方法?我对我的实现不太满意,这通常表明有更好的方法。

我们将不胜感激任何有关实现此目标的更好方法的建议。

谢谢。

请您参考如下方法:

对不起,我很难按照你的例子去做;虽然我认为这就是你想要的。

django Querest 有一个 .update() 方法,可以将新属性传递给更新,并且值将保留。

my_django_class.objects.all().update(my_class_attr=new_value) 

要获取查询集,您可以在查询中使用相关名称。 Django 默认生成它们,但我发现显式定义它们更好。这个This stack question addresses them well .

这样,您的方法将如下所示(如果我没看错的话):

def _update_currancies(self): 
    Some_other_model(_the_related_name__field = main_model).update(attr = new_value) 

我发现最好不要在触发请求时更新表。通常,我只会添加另外两个字段,每次输入值发生变化时(在本例中为美元),使用方法来更新附加字段(可以通过覆盖保存方法来完成)。

对于您的情况,它看起来像这样:

class main_model_example(models.Model): 
   us_number = models.DecimalField(max_digits=20, decimal_places=2, default=0.00) 
   eur_number = models.DecimalField(max_digits=20, decimal_places=2, default=0.00) 
   ccy_number = models.DecimalField(max_digits=20, decimal_places=2, default=0.00) 
 
   def _update_currancies(self): 
       #update and set new currency values 
       #e.g. self.eur_number = self.us_number * .96 
 
   def save(self, *args, **kwargs): 
       self._update_currancies() 
       super(main_model_example, self).save(*args, **kwargs)