Django:实例化模型时如何加载相关模型对象

时间:2019-09-11 23:21:46

标签: django model

我有两个相关的模型(1-n)。在父模型中,我正在子模型上执行很多操作。对于每个操作,我都会调用:

ItensOrder.objects.filter(order=self.pk)

在作为父类的Order类内部,我多次使用了children对象,如下所示:

def total(self):
    itens = ItensOrder.objects.filter(order=self.pk)
    valor = sum(Counter(item.price * item.quantity for item in itens))
    return str(valor)

def details(self):
    itens = ItensOrder.objects.filter(order=self.pk)
    return format_html_join('\n', "{} ({} x {} = {})<br/>", 
                            ((item.item.name,str(item.quantity),item.price,str(item.price * item.quantity)) for item in itens))

仅一次加载相关对象的最佳方法是什么,因此我可以避免每次需要相关对象时都访问数据库。

我一直在父模型上尝试过这个:

def __init__(self, *args, **kwargs):
    if self.pk is not None:
        self.itens = ItensOrder.objects.filter(order=self.pk)
    else:
        self.itens = None

但这是错误的。...

任何人都可以帮助!!

2 个答案:

答案 0 :(得分:0)

您可以使用ForeignKey字段的related_name来访问相关的子对象

order = Order.objects.get(id=1)
itens = order.itensorder_set.all()

默认情况下,此反向关系属性将是小写的型号名称,后跟“ _set”,您可以通过在外键上设置related_name来更改此设置

您可以使用prefetch_related

用所有相关对象的缓存预填充此属性。
order = Order.objects.prefetch_related('itensorder_set').get(id=1)
order.itensorder_set.all()  # This can be called multiple times but will not hit the database

以您的情况

class Order(models.Model):

    def total(self):
        valor = sum(Counter(item.price * item.quantity for item in self.itensorder_set.all()))
        return str(valor)

    def details(self):
        return format_html_join('\n', "{} ({} x {} = {})<br/>", 
                        ((item.item.name,str(item.quantity),item.price,str(item.price * item.quantity)) for item in self.itensorder_set.all()))

并在模型管理员中覆盖get_queryset

def get_queryset(self, request):
    return super().get_queryset(request).prefetch_related('itensorder_set')

答案 1 :(得分:0)

您可以在函数内使用select_related

def total(self):
  itens = ItensOrder.objects.select_related('order').filter(order=self)
  valor = sum(Counter(item.price * item.quantity for item in itens))
  return str(valor)

def details(self):
   itens = ItensOrder.objects.select_related('order').filter(order=self)
   return format_html_join('\n', "{} ({} x {} = {})<br/>", 
  ((item.item.name,str(item.quantity),item.price,str(item.price * item.quantity)) for item in itens))