как правильно реализовать ExpressionWrapper, F и Sum в Django - PullRequest
0 голосов
/ 14 июня 2019

У меня есть две модели Product и Damaged.У товара есть количество предмета, а у Damaged - количество поврежденного предмета.В моем шаблоне list_product я указал общее количество каждого продукта.Когда я добавляю число broken_quantity в поврежденную модель, оно должно быть вычтено из общего количества в Product.Я реализовал следующий код.Все отлично работаетЕдинственная проблема, с которой я сталкиваюсь, - это если общее количество количества в товаре равно количеству поврежденных_количество от поврежденных, оно не показывает 0 в шаблоне product_list.Как ее решить?

models.py

class Damaged(models.Model):
    product = models.ForeignKey('Product', on_delete=models.CASCADE)
    damaged_quantity = models.IntegerField(default=0)

class Product(models.Model):
    name = models.CharField(max_length=250)
    quantity = models.IntegerField()

views.py

def list_product(request):


    products = Product.objects.annotate(
    damaged_product_quantity=Sum('damagedproducts__damaged_quantity'))

    updated_product = products.annotate(
    real_quantity = When(
        Case(quantity__gt=F('damaged_product_quantity'), then=F('quantity')-F('damaged_product_quantity')),
        Case(quantity__lte=F('damaged_product_quantity'), then=Value(0)),
        output_field=IntegerField(),
    )
)

    damaged_products = Damaged.objects.all()

    return render(request, 'pos/list_product.html', {'products': products, 'damaged': damaged_products})

шаблон списка_продуктов

{% if not product.real_quantity %}
    {{product.quantity}}

{% else %}
  {{ product.real_quantity }}
{% endif %}

трассировка стека

Environment:


Request Method: GET
Request URL: http://127.0.0.1:8000/pos/list/product/

Django Version: 2.2
Python Version: 3.6.8
Installed Applications:
['django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django.contrib.humanize',
 'pos',
 'bootstrap4']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']



Traceback:

File "/anaconda3/envs/django/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
  34.             response = get_response(request)

File "/anaconda3/envs/django/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  115.                 response = self.process_exception_by_middleware(e, request)

File "/anaconda3/envs/django/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  113.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/Users/web99/Desktop/onlinezeal/PosProject/pos/views.py" in list_product
  369.         output_field=IntegerField(),

File "/anaconda3/envs/django/lib/python3.6/site-packages/django/db/models/expressions.py" in __init__
  863.             raise TypeError("__init__() takes either a Q object or lookups as keyword arguments")

Exception Type: TypeError at /pos/list/product/
Exception Value: __init__() takes either a Q object or lookups as keyword arguments

1 Ответ

0 голосов
/ 14 июня 2019

Вы можете попробовать вот так:

products = Product.objects.annotate(damaged_product_quantity=Sum(
'damagedproducts__damaged_quantity')).annotate(
real_quantity=F('quantity')-F('damaged_product_quantity'))

Здесь вам не нужен ExpressionWrapper, поскольку оба значения quantity и damaged_product_quantity являются целочисленными.

Использование условного выражения:

from django.db.models import Value, When, Case

products = Product.objects.annotate(
    damaged_product_quantity=Sum('damagedproducts__damaged_quantity'))

updated_product = products.annotate(
    real_quantity = When(
        Case(quantity__gt=F('damaged_product_quantity'), then=F('quantity')-F('damaged_product_quantity')),
        Case(quantity__lte=F('damaged_product_quantity'), then=Value(0))
    )
)

Документация может быть найдена here.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...