You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django多对多自关联场景下Record多级祖先收益计算实现问题

多级祖先分成逻辑实现方案

你的现有代码缺少两个核心逻辑:

  1. 没有对祖先节点做层级遍历,无法区分不同层级的分成比例
  2. 修改的是关联用户的收入属性,最后调用self.items.save()不会生效,需要单独保存用户的userprofile对象

核心分成规则对应逻辑

首先计算单条新Record的可分配总金额:

per_item_total = self.cost / self.items.count()

每向上追溯一级,可分配金额就对半拆分,所以第k级祖先(k从1开始,直接父节点为第1级)的分成是 per_item_total / (2 ** k)。

修正后的完整calculate_income方法

from django.db import transaction

class ExtendPurchase(models.Model):
    # 原有字段保持不变
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    items = models.ManyToManyField(Record)
    date = models.DateField(auto_now_add=True)
    cost = models.PositiveIntegerField()

    @transaction.atomic
    def calculate_income(self):
        if not self.items.exists():
            return
        per_item_total = self.cost / self.items.count()
        for item in self.items.all():
            # 兼容你原有逻辑:新Record作者为一级分成方,拿总金额的1/2
            item.author.userprofile.income += per_item_total / 2
            item.author.userprofile.save()

            # 层级遍历的当前节点列表,初始是直接祖先(第2级)
            current_level_nodes = list(item.extending.all())
            # 第2级的分母是2^2=4,也就是你要找的delimiter初始值
            current_divider = 4
            # 记录已访问节点,避免有向图存在环导致死循环
            visited = set()
            while current_level_nodes:
                next_level_nodes = []
                for ancestor in current_level_nodes:
                    if ancestor.id in visited:
                        continue
                    visited.add(ancestor.id)
                    # 给当前层级的祖先加收入
                    ancestor.author.userprofile.income += per_item_total / current_divider
                    ancestor.author.userprofile.save()
                    # 收集上一级祖先,作为下一轮遍历的节点
                    next_level_nodes.extend(list(ancestor.extending.all()))
                # 下一级分母翻倍,匹配每级分剩余金额一半的规则
                current_divider *= 2
                # 剩余金额如果小于1分可以提前终止,避免无意义的计算
                if per_item_total / current_divider < 0.01:
                    break
                current_level_nodes = next_level_nodes

关键说明

  • 代码里的current_divider就是你要找的delimiter,每往上一级乘以2,刚好对半拆分剩余金额
  • 加了事务原子性保证,要么所有收入都更新成功,要么都不更新,避免数据不一致
  • 加了访问记录防止图有环导致死循环,同时加了最小金额阈值提前终止遍历,提升性能
  • 每个userprofile修改后单独调用save方法,保证修改持久化

内容的提问来源于stack exchange,提问作者Pavel Shlepnev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 10:15:10