【问题标题】:Django Exists() / ~Exists() return if there is no matching data?如果没有匹配的数据,Django Exists() / ~Exists() 返回?
【发布时间】:2020-05-28 13:56:38
【问题描述】:

编辑:

根据下面 Schillingt 的回答,我已切换到使用 Case/When:

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

【问题讨论】:

    标签: django django-queryset exists not-exists django-subquery


    【解决方案1】:

    如果 False 和 None 之间的大小写不同,则不能使用 Exists。这是一个严格的布尔运算。您将需要使用返回 NullableBooleanFieldSubquery,其结果是使用 WhenCase 计算得出的

    【讨论】:

    • 嗨,谢谢,这更有意义,但我现在正在努力解决有关字段值无法识别的错误:/retailers/A001/ 的 FieldError 无法解析表达式类型,未知 output_field 我的查询:上下文['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())))) 抱歉,这对我来说是全新的......
    • 对传入子查询的查询集进行注释。然后使用.values(),参数是带注释的字段名称。
    • 抱歉,您能否详细说明一下,我不确定我是否理解?我移动了 .annotate() 但收到有关未定义 in_db 名称或 Case 不可迭代的错误...或没有属性 .values()
    • .annotate(outer_in_db=Subquery(suppliers.filter().annotate(inner_in_db=When(Case(...))).values('inner_in_db')[:1]))
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多