【问题标题】:How do I access another model's database to carry out some calculation in my current model field in Django?如何访问另一个模型的数据库以在 Django 的当前模型字段中执行一些计算?
【发布时间】:2021-09-21 11:16:09
【问题描述】:

首先,这里是sample project is available,以便任何人都可以查看并告诉我哪里出错了。

我有两个模型,Package 和 Receivables。在 Package 中,有一个字段 total_package,而在 Receivables 中,最初有两个字段,discount 和approved_pa​​ckage。我想访问 total_package 并从中减去折扣以自动填充approved_pa​​ckage 字段。如果您查看项目的 test.js 文件,我尝试使用 JS 来实现相同的目的,但这并不符合我的意图。我不知道我哪里出错了。我还想了解如何使用纯 django 方式实现这一目标。有人可以帮我吗?

模型:

class Package(models.Model):
    rt_number=ForeignKey(Patient, on_delete=CASCADE)
    diagnosis=models.ForeignKey(Diagnosis, on_delete=CASCADE)
    treatment=ForeignKey(Treatment, on_delete=CASCADE)
    patient_type=ForeignKey(PatientType, on_delete=CASCADE)
    date_of_admission=models.DateField(default=None)
    max_fractions=models.IntegerField(default=None)
    total_package=models.DecimalField(max_digits=10, decimal_places=2)

class Receivables(models.Model):
    rt_number=ForeignKey(Patient, on_delete=CASCADE)
    discount=models.DecimalField(max_digits=9, decimal_places=2, default=None)
    approved_package=models.DecimalField(max_digits=10, decimal_places=2, default=None)
    proposed_fractions=models.IntegerField()
    done_fractions=models.IntegerField()
    base_value=models.DecimalField(max_digits=10, decimal_places=2)
    expected_value=models.DecimalField(max_digits=10, decimal_places=2)

希望在这个问题上得到一些帮助。提前致谢。

【问题讨论】:

    标签: javascript html python-3.x django django-models


    【解决方案1】:

    首先,您需要从Package的外键访问对应的Package对象的total_package。然后,您可以根据需要执行计算。 就像如果 r1 是一个 Receivables 对象并且它通过外键链接到 Package Object,那么我们可以这样做。

    r1.approved_package = r1.package.total_package - r1.discount
    r1.save()
    

    注意 - 在执行此操作之前,请确保 r1 已链接到 Package 对象

    【讨论】:

      【解决方案2】:

      在这两个类中,你有一个共同的字段,它是什么 rt_number。因此,您可以设置一个属性以从 Receivable 模型类中获取一个 Package 对象,并使用它来计算或做任何您想做的事情。

      在 Recivables 类中:

      from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
      
      class Receivables(models.Model):
          rt_number=ForeignKey(Patient, on_delete=CASCADE) # This is the common field in both class
          .....
      
          @property
          def package(self):
              """Return a package object or None if not exists"""
              try:
                  return Package.objects.get(rt_number=self.rt_number)
              except ObjectDoesNotExist:
                  return None
              except MultipleObjectsReturned:
                  # You'll need to write some code to know what package to use
                  # By example, return last Package
                  return Package.objects.filter(rt_number=self.rt_number).last()
      
          
          def calculate_aproved_discount(self):
              """Calculates the discount taken the package as reference"""
              if(self.package):
                  # make here your calculations
                  return self.package.total_package - self.discount
              else: # package does not exists
                  # You can not calculate the approved package
                  return 0 # or whatever you want in these case
      
          # Overrides django model save method to autocalculate the discount when object is saved
          def save(self, *args, **kwargs):
              self.aproved_package = self.calculate_aproved_discount() # Calculate aproved_discount field
              super(Receivables, self).save(*args, **kwargs) # call save in ancestror
      
      

      另外,我认为你的 total_package 不应该是模型字段的一部分,应该是一个简单的方法或属性(如装饰的 def 包),并且只在需要时计算它,而不是每次保存对象时计算。但可能在您的要求中,您出于某种原因需要存储它。而且,这很重要,如果 Patient 只能有一个 Package 模型关联,请更改 rt_number 外键以实现一对一关系。

      【讨论】:

      • 非常感谢。我编写了方法并将 rt_number 外键更改为 OneToOneField。我指挥了makemigrations,效果很好。但是当我尝试迁移时,'django.db.utils.IntegrityError: UNIQUE constraint failed: new__account_package.rt_number_id' 出现在终端中。您可以在我最初在帖子中提供的 github 链接中看到更改。
      • 好的,处理迁移需要你阅读很多关于如何应用它并在不同环境中处理此类问题的信息。所以忘记 OneToOne 关系并再次写回 ForeingKey。 ForeingKey 的问题是它可以为 Patient 返回多个 Package 对象,这没有问题,但在这种情况下,您必须编写一些代码来选择其中一个。考虑到包可能返回多个对象,我编辑了示例以重写包属性。
      • 谢谢。它现在确实有效。但我刚刚发现它完全是硬编码的。我的意思是无论我在approved_pa​​ckage中输入多少金额,默认情况下它都会执行计算并将结果保存在数据库中,但我想要的是当用户在折扣字段中输入金额时,approved_pa​​ckage字段应该有一个初始值这是由计算返回的,但用户应该能够改变它。如果要求不高,我该怎么做?抱歉,我之前的问题不清楚。
      • 阅读模型字段。您可以设置一个默认值,它可以是一个表达式或一个硬编码值或调用一个方法来解析,这个默认值将在创建新对象时呈现给用户,用户也可以更改此值,用户也可以更改数据,可以在 save 方法中截取并应用、拒绝或计算其他不同的折扣。我想我回答了你最初的问题:) 最后,最好提取模型之外的所有业务逻辑,并将模型集中在数据存储中,并询问模型之外的其他类或函数的折扣
      • 注明。会这样做。再次感谢您的时间和帮助。 :)
      猜你喜欢
      • 1970-01-01
      • 2019-09-30
      • 1970-01-01
      • 2013-06-12
      • 2020-08-08
      • 2017-04-11
      • 1970-01-01
      • 2019-09-07
      • 2022-11-14
      相关资源
      最近更新 更多