我有一个问题有点难以解释,请原谅我。首先,这里有一些相关的版本,以防出现问题:Django 2.0.3、python3.6.4、postgresql10.3。在
基本上,我对我的一些Django模型有这样的结构:
class Capability(models.Model):
relationships = models.ManyToManyField('self',
symmetrical=False,
through='CapabilityRelationship',
blank=True)
name = models.CharField(max_length=255)
class CapabilityRelationship(models.Model):
from_capability = models.ForeignKey(Capability,
on_delete=models.CASCADE,
related_name='from_set',
blank=True,
null=True)
to_capability = models.ForeignKey(Capability,
on_delete=models.CASCADE,
related_name='to_set')
number = models.PositiveSmallIntegerField(validators=[MinValueValidator(1)])
def _get_complete_numbers(self):
# generate the complete numbers using depth-first search
def save(self, *args, **kwargs):
# Get the complete numbers before saving. If we're not able to generate the complete numbers, something is
# wrong, an error will be raised, and we don't want to save.
complete_numbers = self._get_complete_numbers()
super().save(*args, **kwargs) # Call the "real" save() method.
# Delete all old complete numbers.
self.capabilityrelationshipcompletenumber_set.all().delete()
# Save the new complete numbers.
for complete_number in complete_numbers:
CapabilityRelationshipCompleteNumber.objects.create(capability_relationship=self,
complete_number=complete_number)
class CapabilityRelationshipCompleteNumber(models.Model):
capability_relationship = models.ForeignKey(CapabilityRelationship, on_delete=models.CASCADE)
complete_number = models.CharField(max_length=255, unique=True)
为了用文字描述这些模型,我有一个Capability
模型,它与自身有多对多的关系(在CapabilityRelationship
中捕获)。实际上,这将是一个“树”,其中每个节点可以有多个子节点和多个父节点(即,它是一个有向无环图)。最后,每个关系实例可以有多个“完整数字”(在CapabilityRelationshipCompleteNumber
中捕获)。在
“数字”和“完全数”背后的概念本质上是杜威十进制。完整的1.2.3.4将有4个级别的Capability
对象,其中1是最顶层(即根节点),4是叶。因为我在上面列出的结构是一个DAG而不是一棵树,一个节点实际上可以有多个这样的“完整”数字,因为从任何给定的节点到它的根都可以有多条路径。在
如果这个描述不成立,请让我知道,我可以模仿一些东西在油漆。在
我重写了CapabilityRelationship.save()
方法,因为每次关系更改时都需要重新计算完整的数字,因为number
可能已经更改。所以我要做的就是简单地计算新的完整数,删除所有旧的完整数,然后保存新的。在
我遇到的问题是我根本无法删除旧的完整数字,这让我很困惑。我想知道是否有什么关于重写CapabilityRelationship.save()
的东西我根本就不明白。例如:
如果我访问管理站点并将叶节点的number
设置为1,保存它,然后将其修改为2,我得到以下输出:
现在,所有这些看起来都很好,但是当我访问管理站点以获得所有完整数字的列表时,我看到到目前为止计算的所有8个完整数字,而不是将number
更改为2后当前正确的4。如果我打开一个Python shell并列出完整的数字,我会看到到目前为止创建的所有数字:
> ./manage.py shell
Python 3.6.4 (default, Dec 19 2017, 15:24:51)
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.39.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from src.apps.api.models.capability import *
>>> CapabilityRelationshipCompleteNumber.objects.all()
<QuerySet [<CapabilityRelationshipCompleteNumber: 1.1.1.1>, <CapabilityRelationshipCompleteNumber: 1.1.1.2>, <CapabilityRelationshipCompleteNumber: 1.2.1.1>, <CapabilityRelationshipCompleteNumber: 1.2.1.2>, <CapabilityRelationshipCompleteNumber: 1.3.1.1>, <CapabilityRelationshipCompleteNumber: 1.3.1.2>, <CapabilityRelationshipCompleteNumber: 2.2.1.1>, <CapabilityRelationshipCompleteNumber: 2.2.1.2>]>
如果我使用psql直接查看数据库,我会看到同样的情况。在
显然,无论出于什么原因,delete调用实际上并没有发生。我尝试过CapabilityRelationshipCompleteNumber.objects.filter(capability_relationship=self).delete()
,CapabilityRelationshipCompleteNumber.objects.all().delete()
,并使用connection.cursor()
发出一个原始SQL DELETE FROM api_capabilityrelationshipcompletenumber;
。似乎什么都不管用。我不明白发生了什么事。我已经阅读了Django文档中关于删除查询集并重写save()
,但是我没有看到任何可以帮助我诊断问题的东西。在
有人知道这是怎么回事吗?非常感谢任何帮助。请让我知道,如果我可以澄清任何这一点。在
好吧,我是在一整天的网络调试和挖掘之后发现的。据我所知,问题似乎出在Django如何挽救许多关系上。如https://stackoverflow.com/a/1925784/1269634所述:
尽管这篇文章最初可以追溯到2009年,但这种烦恼在django2.0中显然仍然存在。看完这篇文章,我相信这就是造成这种奇怪的原因。不幸的是,据我所知,Django文档中没有记录这一点,这就是为什么花了这么长时间才找到并修复的原因。在
解决这个问题的方法变得相对简单。我有效地将} 。管理实现现在如下所示:
CapabilityRelationship.save()
重命名为CapabilityRelationship.update_complete_numbers()
。然后,我修改了Capability
管理实现来覆盖^{这很管用!神奇的是,更新完整的数字发生在模型保存完成之后(当
super().save_related(request, form, formsets, change)
返回时是真的)。在感谢大家的帮助!我希望这最终能帮助其他人。在
相关问题 更多 >
编程相关推荐