编辑:
根据下面席林特的回答,我已切换到使用案例/何时:
context['db_orders'] = Order.objects.filter(
retailer_code=self.object.retailer_code).annotate(
in_db=Case(When(Q(Subquery(self.object.suppliers.filter(
supplier_code=(OuterRef('supplier_code')))
), then=Value(True), default=Value(False), output_field=NullBooleanField()))))
但是我现在正在努力解决一个错误:
FieldError at /retailers/A001/
Cannot resolve expression type, unknown output_field
原始问题:
我在下面有一个带有查询/子查询的 DetailView,该查询/子查询检查供应商代码是否存在于第二个模型的实例中,该模型设置为表示接收到实时库存数据库的采购订单。
这样做的目的是作为一个清单/清单,它将返回是否已收到每个预计发送订单的供应商的订单。
让它返回有一个匹配项似乎工作正常,如果有一个它无法识别的值(我故意创建了一个与列表不匹配的无效订单),它将返回没有匹配项.
但是我需要这个也告诉我根本没有数据,但我似乎无法实现这一点。
例如,下面显示了模板输出;G001 是我设置的“假”代码,G002 是供应商列表中存在的有效代码。但是,如果没有 G002 的订单,它将不会返回任何内容。
Order not received: G001
Order received: G002
我尝试为作为 context['db_orders'] 镜像的上下文编写第二个查询,但使用 ~Exists() 然后将 if 语句嵌套在模板中,但这只会告诉我订单既存在又不存在'不存在,反之亦然。
context['not_db_orders'] = Order.objects.filter(
retailer_code=self.object.retailer_code).annotate(in_db=~Exists(squery))
我也尝试在模板中使用'is not'或'is None'或'is False'来执行此操作,但似乎无法获得我需要的输出
最终,预期的输出是一个表格,其中列出了特定零售商预期的所有供应商,根据订单是否存在于 Order 实例中,它们旁边会出现某种“是”或“否”。(模板 HTML 目前没有反映这一点,但这不是问题)
模板:
{% extends 'tick_sheet/base.html' %}
{% block content %}
<h1>{{ object.retailer_name }}</h1>
<ul>
{% for supplier in object.get_supplier_values %}
<li>{{ supplier }}</li>
{% endfor %}
</ul>
<ul>
{% for item in db_orders %}
{% if item.in_db %}
<li>Order received: {{ item.supplier_code }} - {{ item.supplier_name }}</li>
{% elif not item.in_db or item.in_db is None %}
<li>Order not received: {{ item.supplier_code }} - {{item.supplier_name}}</li>
{% endif %}
{% endfor %}
</ul>
{% endblock content %}
细节视图:
class RetailerDetailView(DetailView):
model = Retailer
slug_field = 'retailer_code'
slug_url_kwarg = 'retailer_code'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['now'] = timezone.now()
context['title'] = 'Order Checklist'
squery = self.object.suppliers.filter(
supplier_code=OuterRef('supplier_code'))
context['db_orders'] = Order.objects.filter(
retailer_code=self.object.retailer_code).annotate(in_db=Exists(squery))
return context
模型.py
from django.db import models
from django.utils import timezone
class Order(models.Model):
''' To simulate connection to main stock db '''
retailer_code = models.CharField(max_length=4)
retailer_name = models.CharField(max_length=100)
supplier_code = models.CharField(max_length=4)
supplier_name = models.CharField(max_length=100)
order_reference = models.CharField(max_length=20)
despatch_date = models.DateTimeField(default=timezone.now)
def __str__(self):
return f"< {self.order_reference}', {self.supplier_name}, {self.retailer_name} >"
# -------------------------------------------------------------------------------------
class Retailer(models.Model):
retailer_code = models.CharField(max_length=4)
retailer_name = models.CharField(max_length=100)
suppliers = models.ManyToManyField('Supplier')
slug = models.SlugField(unique=True, null=True)
def get_supplier_values(self):
return [(suppliers.supplier_code + ' - ' + suppliers.supplier_name) for suppliers in self.suppliers.all()]
def save(self, *args, **kwargs):
self.slug = self.slug or slugify(self.retailer_code)
super().save(*args, **kwargs)
def __str__(self):
return f"< {self.retailer_code} - {self.retailer_name} >"
class Supplier(models.Model):
supplier_code = models.CharField(max_length=4)
supplier_name = models.CharField(max_length=100)
def __str__(self):
return f"< {self.supplier_code}, {self.supplier_name} >"