Django制作与其他字段(对象)值相关的字段

时间:2019-10-31 13:39:31

标签: django django-models

我用Odoo框架工作了几年。而且Odoo具有非常好的功能,例如:

partner_id = field.Many2one(Partner)
partner_name = fields.Char(string='Partner name', related='partner_id.name')

基本上,只要您从合作伙伴表中分配了不同的partner_id,就会自动分配partner_name。现在,我开始使用django(绝对的新手),但似乎找不到类似的功能。 我的问题是该问题可能有什么解决方案。也许已经建立了具有这种功能的外部库? 预期结果:

product = models.ForeignKey(Product)
product_color = models.CharField(string='Partner name', related='product.color')

请记住,产品对象将具有颜色字段,并且每当产品字段值产品对象颜色值更改时,它就会被分配给product_color。另外,将其存储到数据库又如何呢?如果可以选择将其存储在数据库中还是即时获取它,那就太好了。

干杯!

2 个答案:

答案 0 :(得分:1)

创建吸气剂非常容易,因为您可以简单地使Python对象中的函数表现为属性:

class SampleModel(models.Model):
    product = models.ForeignKey(Product)

    @property
    def product_color(self):
         return self.product.color

这确实会即时检索属性,这将导致对数据库的调用。

答案 1 :(得分:0)

重复数据通常是(更严格的)反模式。即使在同一数据库中的两个表中,同步数据通常也比预期的难。即使您使用例如Django的信号框架,某些Django ORM调用也可以绕开它(例如.update(..) [Django-doc])。但是,即使您能以某种方式涵盖这些情况,与该数据库对话的另一个程序也可能会更新两个字段之一。

大多数数据库都有触发器可以提供帮助。但是同样,要处理的案件数量通常比预期的要大。例如,如果我们引用的Product被删除,或者外键现在指向另一个Product,那么我们将需要更新该字段。

因此,最好在需要时获取相关产品的名称。我们可以通过(a)定义一个属性来做到这一点;或(b)在管理器中做注释。

定义属性

我们可以定义一个属性,以加载相关产品并获取相关名称,例如:

class Order(models.Model):
    product = models.ForeignKey(Product, on_delete=models.PROTECT)

    @property
    def product_name(self):
        return self.product.name

然后,我们可以使用some_order.product_name获取产品名称。如果我们需要经常获取它,这可能不是很有效,因为默认情况下,这些关系是在Django中延迟加载的,因此可能会导致 N + 1问题

注释查询集

我们可以做一个注释,在获取Order时在同一查询中获取产品名称,例如:

from django.db.models import F

class OrderManager(models.Manager):
    def get_queryset(self):
        return super().get_queryset().annotate(
            product_name=F('product__name')
        )

class Order(models.Model):
    product = models.ForeignKey(Product, on_delete=models.PROTECT)

    objects = OrderManager()

然后,如果我们获取订单。例如,对于Order.objects.get(pk=1),则该Order对象将具有一个名为product_name的属性product

相关问题