Многоуровневый доступ с помощью отношений ManyToMany в Django
У меня есть модели, объекты из которых можно представить в виде направленного графа:
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")),
),
]
Когда создается новый экземпляр Record
и он имеет связь с другим экземпляром через модель Extend
, я хотел бы вычислить атрибут author.user.userprofile.income
в экземпляре User
. Проблема в том, что я не знаю, как вычислить этот атрибут для всех предков вновь созданного Record
, который следует некоторому правилу: если вновь созданный Record
стоит 50, предок первого уровня получает 25, а 25 переходит к другим предкам, постоянно делясь на 2.
Я могу написать формулу для предка первого уровня, но что для остальных?
# 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()
Если я правильно понимаю, вы хотите рекурсивно просмотреть записи и разделить на 2 стоимость в каждом цикле.
Может ли это сработать для вас?
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()