Я пытался научиться использовать сигналы, и, к сожалению, мой код ниже не работает.Кроме того, я натолкнулся на дюжину постов, в которых все показывают разные способы сделать это.
Моя цель в этом посте - прояснить и прийти к консенсусу в отношении написания сигналов наилучшим возможным способом в 2019 году длямасштабируемость.В этом примере используется post_save.
model.py
from django.db import models
from metrics.models import InventoryProduct
from product.models.product import Product
class PurchasedOrder(models.Model):
__quantity_sold = None
product = models.ForeignKey(Product, on_delete=models.CASCADE)
purchase_quantity = models.IntegerField()
quantity_sold = models.IntegerField(default=0)
def __init__(self, *args, **kwargs):
super(PurchasedOrder, self).__init__(*args, **kwargs)
self.__original_quantity_sold = self.quantity_sold
def save(self, *args, **kwargs):
# If the quantity sold field has changed run the update_sold_out method
if self.quantity_sold != self.__original_quantity_sold:
PurchasedOrderLogic.update_sold_out(self)
super(PurchasedOrder, self).save(*args, **kwargs)
self.__original_quantity_sold = self.quantity_sold
def __str__(self):
return self.product.name
signal.py:
from django.db.models.signals import post_save
from django.dispatch import receiver
from purchasing.models import PurchasedOrder
from purchasing.services.models_logic import PurchasedOrderLogic
@receiver(post_save, sender=PurchasedOrder)
def update_inventory_product_total_qty_purchased(sender, instance):
PurchasedOrderLogic.update_inventory_product_total_qty_purchased(
sender, instance.product.id, instance.purchase_quantity
)
Здесь находится моя логика.Когда я обновляю поле Purchase_Order purchase_quantity, оно также должно обновлять поле total_qty_purchased InventoryProduct.
purchase.services.models_logic.py
class PurchasedOrderLogic(object):
@static_method
def update_inventory_product_total_qty_purchased(purchased_order_class, product_id):
inventory_product = InventoryProduct.objects.get(pk=product_id)
total_qty_purchased = purchased_order_class.objects.filter(product_id=product_id).aggregate(
Sum('purchase_quantity')
).get('purchase_quantity__sum')
inventory_product.total_qty_purchased = total_qty_purchased
inventory_product.save()
apps.py
from django.apps import AppConfig
from django.db.models.signals import post_save
from django.utils.translation import ugettext_lazy as _
from purchasing.models import PurchasedOrder
from purchasing.signals import update_inventory_product_total_qty_purchased
class PurchasingConfig(AppConfig):
name = 'purchasing'
verbose_name = _('purchasing')
def ready(self):
post_save.connect(update_inventory_product_total_qty_purchased, sender=PurchasedOrder)
Чего не хватает?Я не уверен, даже если сигнал работает?
Я запускаю .save (), вручную изменяя любое поле в модели.
Лично я изменил поле purchase_quantity, которое должно печатать это значение, так как оно вызывается внутри метода update_inventory_product_total_qty_purchased