Django - 以一对多的关系改变相关对象的值

时间:2016-02-12 15:54:56

标签: python django django-models one-to-many

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

因此,我在我的模型中添加了一个名为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()的主模型,值将恢复为USD。我假设这是因为xxx_set.all()方法再次从数据库中检索模型(尚未更新)。我想要的是一旦我更新了相关的模型,让它们保留在内存中,所以当我再次使用它们时,保留我设置的更新值我已经阅读了文档并浏览了一些问题,但似乎找不到类似的东西。

所以我有两个问题:

  1. 我想实现的目标是什么?即更新内存中的相关(一对多)模型,传递主模型(进行更多计算),然后在稍后再次引用相关模型时返回更新的值。
  2. 或者我是否需要在偏移集中从主模型中获取所有相关模型并将它们分配给我必须传递给主模型的变量?

    1. 我这样做的事实被认为是坏事吗?即有主模型方法调用相关模型方法?我对我的实施并不十分满意,这通常表明有更好的方法。
    2. 非常感谢任何关于更好地实现这一目标的建议。

      感谢。

1 个答案:

答案 0 :(得分:3)

对不起,但是我很难跟上你的榜样;虽然我认为这是你想要的。

django Queriest有一个.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)

我发现最好不要在触发请求时更新表。通常我只会添加两个其他字段,每次输入值更改(在这种情况下为USD),使用方法只更新其他字段(可以通过覆盖save方法来完成)。

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

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)