简体   繁体   English

如果没有匹配的数据,Django Exists() / ~Exists() 会返回吗?

[英]Django Exists() / ~Exists() return if there is no matching data?

EDIT:编辑:

As per schillingt's answer below I have switched to using Case/When:根据下面 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()))))

However I'm now struggling with an errror:但是我现在正在为一个错误而苦苦挣扎:

FieldError at /retailers/A001/

Cannot resolve expression type, unknown output_field

Original question:原问题:

I have the DetailView below with a query/subquery that checks whether supplier_code exists within instances of a second model set up to represent purchase orders received into a live stock database.我有下面的 DetailView 带有查询/子查询,用于检查供应商代码是否存在于第二个模型的实例中,该模型设置为表示接收到实时库存数据库中的采购订单。

The intention is for this to function as a checklist/ticksheet that will return whether or not the order has been received for each supplier expected to send one.其目的是将其用作清单/票据,该清单将返回是否已收到每个预计发送订单的供应商的订单。

Getting it to return that there is a match seems to be working fine, and if there is a value it does not recognize (I have purposefully created an invalid order that won't match against the list) it will return that there is no match.让它返回有匹配项似乎工作正常,如果有一个它无法识别的值(我故意创建了一个与列表不匹配的无效订单),它将返回没有匹配项.

However I need this to also tell me that there is simply no data, yet I don't seem to be able to achieve this.但是我需要这个来告诉我根本没有数据,但我似乎无法实现这一点。

For example the below shows the template output;例如下面显示了模板输出; G001 is the 'fake' code I have set up and G002 is a valid one that exists in the suppliers list. G001 是我设置的“假”代码,G002 是供应商列表中存在的有效代码。 However if there is not an order present for G002 it will not return anything.但是,如果没有 G002 的订单,它将不会返回任何内容。

    Order not received: G001
    Order received: G002

I have tried writing a second query for the context that is a mirror of context['db_orders'] but using the ~Exists() and then nesting the if statements in the template but this will just tell me that the orders both exist and don't exist or vice versa.我已经尝试为作为 context['db_orders'] 镜像的上下文编写第二个查询,但是使用 ~Exists() 然后在模板中嵌套 if 语句,但这只会告诉我订单既存在又不存在'不存在,反之亦然。

 context['not_db_orders'] = Order.objects.filter(
            retailer_code=self.object.retailer_code).annotate(in_db=~Exists(squery))

I've also tried to do this in the template using 'is not' or 'is None' or 'is False' but cannot seem to get the output I need我也尝试在模板中使用“不是”或“是无”或“是假”来执行此操作,但似乎无法获得我需要的输出

Ultimately the intended output is a table that lists all the suppliers expected into a particular retailer with some manner of 'Yes' or 'No' next to them based on whether the order exists among the Order instances.最终,预期的输出是一个表格,它根据订单实例中是否存在订单,列出了预期进入特定零售商的所有供应商,并在它们旁边以某种方式显示“是”或“否”。 (The template HTML doesn't currently reflect this but that is not the issue) (模板 HTML 目前没有反映这一点,但这不是问题)

Template:模板:

{% 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 %}

The DetailView:细节视图:

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

Models.py模型.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} >"

If there's a difference in the case between False and None you can't use Exists .如果 False 和 None 之间的情况有所不同,则不能使用Exists That is a strictly boolean operation.这是一个严格的布尔运算。 You will need to use a Subquery that returns a NullableBooleanField whose result is calculated with When and Case您将需要使用返回NullableBooleanFieldSubquery ,其结果使用WhenCase计算

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM