как сделать конкретное поле модели динамическим из другой модели - PullRequest
0 голосов
/ 11 июня 2019

У меня есть две модели: Damaged и Product. В модели Product количество продукта зависит от значения Damage_quantity, которое хранится в другой таблице. Например, если значение поврежденного_количества находится в таблице с повреждениями, тогда значение количества в продукте должно быть quantity-damaged_quantity, если damaged.product_id == product.id .Я пытался так, но он не работает

models.py

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

    def __str__(self):
        return self.product


class Product(models.Model):
    name = models.CharField(max_length=250)
    category = models.ForeignKey(Category,on_delete=models.CASCADE)
    quantity = models.IntegerField() 

views.py Я получаю доступ к набору запросов продукта, как это в моих представлениях

def list_products(request):
products = Product.objects.annotate(damaged_product_quantity=Sum('damagedproducts__damaged_quantity')).annotate(
        real_quantity=ExpressionWrapper(F('quantity') - F('damaged_product_quantity'), output_field=IntegerField()))

list_product_template. Здесь, при отображении real_quantity, если повреждения.damaged_quanity и product.quantity равны euqal, тогда оно не меняет значение. Вместо того, чтобы стать нулевым, оно не меняет значение. В другом случае оно работает нормально.

                {% if not product.real_quantity %}
                {{product.quantity}}
                {% elif product.real_quantity == product.quantity %}
                 0
                {% else %}
                {{ product.real_quantity }}
                {% endif %}

Страница product_detail

def product_detail(request, slug):
    product = get_object_or_404(Product, slug=slug)
    damaged = Damaged.objects.all()

    return render(request, 'pos/product_detail.html', {'product': product,'damaged':damaged})

шаблон product_detail.Я пытался получить текущее количество продуктов после добавления поврежденных_продуктов, но он не работает хорошо. Он дает мне и {% if %}, и {% else %} часть. Как я могу решить эту проблему?

product quantity:
{% for damage in damaged %}
{% if product.id == damage.product_id %}
{{product.quantity|subtract:damage.damaged_quantity}}
{% else %}
{{product.quantity}}
{% endif %}
{% endfor %}

1 Ответ

1 голос
/ 11 июня 2019

Я думаю, вам нужно переопределить метод сохранения в Damaged модели:

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

    def __str__(self):
        return self.product

    def save(self, *args, **kwargs):
        super(Damaged, self).save(*args, **kwargs)
        self.product.quantity = self.product.quantity - self.damaged_quantity
        self.product.save()

Но это решение может быть несовместимым.Например, если вы попытаетесь обновить поврежденную модель, то значение продукта будет обновлено снова.

Я бы порекомендовал использовать annotation, чтобы связать значение с продуктом, чтобы при необходимости можно было запрашивать.Например:

Для этого добавим поле related_name в Damaged модель:

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

Использование:

from django.db.models import Sum, F, IntegerField

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

real_quantity_more_than_ten = products.filter(real_quantity__gt=10)

for p in real_quantity_more_than_ten:
    print(p.real_quantity)

Обновление

from django.db.models import Sum

def product_detail(request, slug):
    product = get_object_or_404(Product, slug=slug)
    damaged = product.productdamaged.all()
    if damaged.exists():
       damage_amount = damaged.aggregate(d_amount = Sum('productdamaged__damaged_quantity')).get('d_amount', 0)
    else:
      damage_amount = 0

    return render(request, 'pos/product_detail.html', {'product': product,'damage_amount':damage_amount})

# template

{% if damage_amount != 0 %}
   {{product.quantity|subtract:damage_amount}}
{% else %}
   {{product.quantity}}
{% endif %}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...