I have the following function that is called via signal. 1) check if incluencer exists. 2) Increase discount by +1. Currently, I hit the database twice. Is there a better way to write that? Additionally, I wonder I can check 2) all on a database level so I don't need the for-loop.
@receiver(signal=charge_succeeded) @transaction.atomic def create_influencer_transaction(sender, order, charge, **kwargs): order_exists = Transaction.objects.filter(order=order).exists() if order_exists: return None # 1) Check if influencer exists first_order_item = order.order_items.first() influencer = first_order_item.social_referral if not influencer: return None total_points_earned = order.order_items.aggregate( total=Sum( F('unit_points_earned') * F('quantity'), output_field=IntegerField() ) )['total'] or 0 Transaction.objects.create( [...] ) # 2) Redeemed amount + 1 for order_item in order.order_items.all(): social_discount = order_item.social_discount if social_discount: social_discount.redeemed_amount = F('redeemed_amount') + 1 social_discount.save(update_fields=['redeemed_amount']) break
class OrderItem(AbstractItem, AbstractDiscountItem, AbstractSocialItem): order = models.ForeignKey( [...] ) social_discount = models.ForeignKey( 'discounts.SocialDiscount', on_delete=models.PROTECT, related_name='order_items', null=True, blank=True, ) # PROTECT = don't allow to delete the discount if an order_item exists class SocialDiscount(AbstractDiscount): event = models.OneToOneField( [...] ) # CASCADE = delete the discount if the event is deleted tickets = models.ManyToManyField( [...] )