РЕДАКТИРОВАТЬ:
В соответствии с ответом Шиллингта ниже я переключился на использование 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
Я попытался написать второй запрос для контекста, который является зеркалом контекста ['db_orders'], но с использованием ~ Exists () и затем вложенные операторы if в шаблоне, но это просто скажет мне, что заказы существуют и не существуют, или наоборот.
context['not_db_orders'] = Order.objects.filter(
retailer_code=self.object.retailer_code).annotate(in_db=~Exists(squery))
Я также пытался сделать это в шаблон, использующий «нет», «нет» или «ложно», но, похоже, не может получить нужный мне результат
В конечном итоге предполагаемый результат представляет собой таблицу, в которой перечислены все ожидаемые поставщики в конкретном розничном магазине с какой-то тип «Да» или «Нет» рядом с ними в зависимости от того, существует ли порядок среди экземпляров Ордена. (Шаблон 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 %}
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
Модели. 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} >"