Tengo modelos, objetos a partir de los cuales se pueden representar como un gráfico dirigido:
from django.db import models from django.contrib.auth.models import User class Record(models.Model): name = models.CharField(max_length=100) description = models.CharField(max_length=500) content = models.TextField() sequels = models.ManyToManyField('self', blank=True, symmetrical=False, through='Extend', related_name='extending') author = models.ForeignKey(User, on_delete=models.CASCADE) class Extend(models.Model): ancestor = models.ForeignKey(Record, on_delete=models.CASCADE, related_name='+') descendant = models.ForeignKey(Record, on_delete=models.CASCADE, related_name='+') class Meta: constraints = [ models.UniqueConstraint( name="%(app_label)s_%(class)s_unique_relationships", fields=["ancestor", "descendant"], ), models.CheckConstraint( name="%(app_label)s_%(class)s_prevent_self_extend", check=~models.Q(ancestor=models.F("descendant")), ), ] Cada vez que se crea una nueva instancia de Record y tiene una relación con otra instancia a través del modelo Extend , me encantaría calcular el atributo author.user.userprofile.income en la instancia de User . El problema es que no sé cómo calcular este atributo para todos los ancestros del Record recién creado que sigue una regla: si el Record recién creado cuesta 50, el ancestro de primer nivel obtiene 25 y 25 va para otros ancestros, constantemente siendo dividido por 2.
Puedo escribir la fórmula para el antepasado de primer nivel, pero ¿y para los demás?
# In case of some purchase: 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() def calculate_income(self): for item in self.items.all(): item.author.userprofile.income += self.cost / len(self.items.all()) / 2 # first-level; if one would like to extend more than one Record instance for ancestor in item.extending.all(): ancestor.author.userprofile.income += self.cost / delimiter # I don't know what delimiter is to be written self.items.save()Si entiendo correctamente, desea recorrer los registros de forma recursiva y dividir por 2 el costo en cada ciclo.
¿Puede esto funcionar para usted?
class ExtendPurchase(models.Model): # ... def calculate_income(self): def __income_from_record(record, cost): tmp_income = cost for rel in Extend.objects.select_related('descendant').filter(ancestor=record): tmp_income += __income_from_record(rel.descendant, cost/2) return tmp_income for record in self.items.all(): income = __income_from_record(record, self.cost) record.ancestor.author.userprofile.income = income record.ancestor.author.userprofile.save()