0

编辑:

根据下面席林特的回答,我已切换到使用案例/何时:

        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} >"
4

1 回答 1

0

如果 False 和 None 之间的情况不同,则不能使用Exists. 这是一个严格的布尔运算。您将需要使用 aSubquery来返回 a NullableBooleanField,其结果是使用WhenCase计算的

于 2020-02-12T22:59:22.367 回答