Django如何获取所有包含item的发票



我花了两天多的时间在文档和互联网上找,找不到解决方案。我有模型:

class Invoice(models.Model):
(...)
class Product(models.Model):
(...)
class InvoicedItems(models.Model):
invoice = models.ForeignKey(Invoice, on_delete=CASCADE)
article = models.ForeignKey(Product, on_delete=CASCADE)

如何获得包含一个产品的所有发票的列表?我想做一个搜索引擎。

我尝试在InvoicedItems中定义:

def get_invoices_by_article(article):
inv_obj = InvoicedItems.objects.filter(article=article)
inv = inv_obj.invoice
return inv

但是我总是得到错误:'QuerySet' object has no attribute 'invoice'

我知道我很接近,但我需要你的帮助。提前感谢!

你的问题是:'QuerySet' object has no attribute 'invoice'

any.filter()叫它总是返回一个QuerySet对象。或者花哨的list/array

python manage.py shell中的输出说明了这一点:

inv_obj = InvoicedItems.objects.filter(article=article_obj)
print(inv_obj)
# <QuerySet [<Article Object (1)>]>
#    ^ Not an Article Object

所以你的方法将工作与一些小的改变(和一个变量名的改变)

def get_invoices_by_article(article):
inv_list = InvoicedItems.objects.filter(article=article)
inv = inv_list.first().invoice
return inv

但是!这会引发2major问题:

  1. 如果没有匹配的物品怎么办?
  2. 如果有多个呢?

示例解决方案:

def get_invoices_by_article(article):
inv_list = InvoicedItems.objects.filter(article=article)
count = inv_list.count() 
if count == 0:
return None
if count > 1:
# return list of invoices
return [i.invoice for i in inv_list]
# implied: is 1
# return single invoice
return inv_list.first().invoice

# Maybe it's easier to ALWAYS return a List, so it's always a single type!
#   empty or not!
def get_invoices_by_article(article):
return [i.invoice for i in InvoicedItems.objects.filter(article=article)]

在您弄清楚您想要使用该方法的路径之后,我建议把它变成一个模型管理器函数。

当前道:

invoice_item = InvoicedItems.objects.all().first()
my_return = invoice_item.get_invoices_by_article(article_obj)

必须在之前获取一个InvoiceItem Obj你可以用它->额外的工作!

Model Manager方式:

my_return = InvoicedItems.objects.get_invoices_by_article(article_obj)

你剪掉那个db hit!

Basic Model Manager:
from django.db import models
class InvoicedItemsManager(models.Manager):
def get_invoices_by_article(article):
return [i.invoice for i in  InvoicedItems.objects.filter(article=article)]

class InvoicedItems(models.Model):
invoice = models.ForeignKey(Invoice, on_delete=CASCADE)
article = models.ForeignKey(Product, on_delete=CASCADE)
objects = InvoicedItemsManager()

就这么简单!现在您可以为InvoicedItems.objects.添加任意数量的方法


但也许模型方法或管理方法是多余的- idk!由你决定

那么首先让我们来回答你的问题,让我们做一些编辑使一切变得更简单:

将related_name添加到您的字段中:

class InvoicedItems(models.Model):
invoice = models.ForeignKey(Invoice, on_delete=CASCADE, related_name='invoiced_items')
article = models.ForeignKey(Product, on_delete=CASCADE, related_name='invoiced_items')

那么你的查询将看起来像这样:

invoices = Invoice.objects.filter(invoiced_items__article=your_article)

现在让我们让它变得更简单,删除你的自定义类,现在是无用的:

class Product(models.Model):
[...]
class Invoice(models.Model):
[...]
products = models.ManyToManyField(to=Product, related_name='invoices')

并删除你的模型InvoicedItems。

那么你的请求变成:

invoices = Invoice.objects.filter(products=product)

关于ManyToManyFields的更多信息请参见文档

我是这样做的:

def get_invoices_by_article(article):
inv_obj = InvoicedItems.objects.filter(article=article)
return Invoice.objects.filter(invoiceditems__in=inv_obj)

最新更新