限制Django模型中递归的外键深度 [英] Limit Recursive Foreign Key Depth in Django Model

查看:172
本文介绍了限制Django模型中递归的外键深度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个具有可空的ForeignKey到self的Django模型。我有兴趣在递归深度上引入一个极限(比如10)。我应该在哪里找到适合的地方,以及我应该在那里抛出什么样的例外?



我的意思是假的例子:

  def limit_recursion_depth(self):
depth = 0
model = self
而model.parent不是None:
depth + = 1
model = model.parent
如果深度> 10:
pass#在这里抱怨并停止处理
else:
pass#返回模型,保存,正常

对于只能适用于管理员的任何类型的验证,我更喜欢覆盖Model的save()方法的解决方案。 (例如,我想要验证Model.objects.create()。)



更新



即使这个问题在很大程度上是学术性的,与一个我不再追求的项目相关,我想更新这个,以防任何人通过Google发现这个问题。以下是 django-mptt文档


要获得所有这些页面标题,您可能会这样做:

  titles = [] 
而页面:
titles.append(page.title)
page = page.parent

这是每个页面的一个数据库查询 ...


Django-mptt甚至对于小项目来说效率要高得多,我也可能应该在这种情况下使用它。

解决方案

不幸的是,正如这个答案所说明的那样,真的没有在Django中做一个很好的方法。例如,上述方法每次最终用户在更改表单上点击保存按钮时,只会使管理员遇到500错误 - 几乎没有帮助。唯一正确的方法是定义 clean_ {fieldname} 并抛出一个ValidationError 。它不会验证,例如, manage.py shell 中的 model.save(),但是将覆盖验证,例如 queryset.update()



因此,我现在去的解决方案看起来像这样:

  def clean_parent(self):
depth = 0
model = self.instance
而model.parent不是None:
depth + = 1
model = model.parent
如果depth> 10:
raise ValidationError('递归深度超过')

注意这属于管理员


I have a Django model with a nullable ForeignKey to 'self'. I'm interested in introducing a hard limit (say, 10) on the recursion depth. Where would be the proper place to check this and what sort of exception should I throw there?

Pseudo-example of what I mean:

def limit_recursion_depth(self):
    depth = 0
    model = self
    while model.parent is not None:
        depth += 1
        model = model.parent
    if depth > 10:
        pass # Complain here and stop processing
    else:
        pass # Return the model, save, whatever is normal

I am more interested in a solution like overriding the Model's save() method than any kind of validation which will only work for the admin. (For example, I'd like to be able to validate Model.objects.create().)

Update

Even though this question was largely academic and related to a project I'm no longer pursuing, I wanted to update this in case anyone found this through Google. The following is from the django-mptt documentation:

To get all those page titles you might do something like this:

titles = []
while page:
    titles.append(page.title)
    page = page.parent

That’s one database query for each page...

Django-mptt is much more efficient even for small projects and I probably should have been using it even in this case.

解决方案

Unfortunately, as explained very well in this answer, there really isn't a good way to do this in Django. For example, the method above will simply crash the admin with a 500 error every time an end user hits the save button on a change form -- hardly helpful. The only proper way to do this is to define clean_{fieldname} and throw a ValidationError. It doesn't validate, for example, a model.save() from the manage.py shell, but neither will overriding that validate, for instance, queryset.update().

Therefore, the solution I went with now looks like this:

def clean_parent(self):
    depth = 0
    model = self.instance
    while model.parent is not None:
        depth += 1
        model = model.parent
    if depth > 10:
        raise ValidationError('Recursion Depth Exceeded')

Note this belongs in the admin form for the model.

这篇关于限制Django模型中递归的外键深度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆