【问题标题】:How to limit nubmer of Foreign key relations in Django ORM?如何限制 Django ORM 中外键关系的数量?
【发布时间】:2020-10-22 15:54:27
【问题描述】:

我有一个与自身递归相关的模型。其内容如下。

class Category(models.Model):
    name = models.CharField(max_length=200)
    parent = models.ForeignKey(
        'self', blank=True, null=True,
        related_name='children', on_delete=models.CASCADE)

    class Meta:
        verbose_name_plural = "Categories"

    def __str__(self):
        path = [self.name, ]
        node = self.parent
        while node is not None:
            path.append(node.name)
            node = node.parent
        return '->'.join(path[::-1])

我想要实现的是一个小验证,防止超过 3 个孩子进入父类别。 例如,如果我按照上面的状态创建,它将保存如下:

Programming->Back-end->Python->ifelse.

我的问题:如何防止父类别有超过 3 个孩子?

【问题讨论】:

  • 我很困惑:您是在问不能在上面创建类别“ifelse”,还是说类别“Python”不能有超过 3 个子项(“ifelse”,“ for", "while", 但不是 "trycatch")?

标签: django foreign-keys django-orm


【解决方案1】:

你可以试试model validation

from django.core.exceptions import ValidationError


class Category(models.Model):
    name = models.CharField(max_length=200)
    parent = models.ForeignKey(
        'self', blank=True, null=True,
        related_name='children', on_delete=models.CASCADE)

    def clean(self):
        if self.parent:
            if self.get_parents_length(self) > 3:
                raise ValidationError("Parent has already got 3 children!")

    class Meta:
        verbose_name_plural = "Categories"

    def __str__(self):
        path = [self.name, ]
        node = self.parent
        while node is not None:
            path.append(node.name)
            node = node.parent
        return '->'.join(path[::-1])

    @staticmethod
    def get_parents_length(cat):
        parents = [cat.name]
        node = cat.parent
        while node is not None:
            parents.append(node.name)
            node = node.parent
        return len(parents)

【讨论】:

  • 只要把它放在 save() 中。不要在 save 中调用full_clean:最好的情况是它会被调用两次,最坏的情况是它会在不需要的地方进行模型验证(例如在信号中)。
  • @Melvyn,我能想到的最好的客户端是在视图中,就像文档所说的那样,你能帮忙解释一下,为什么如果把 full_clean 放在 save 里面会被调用两次
  • @minglyu 我已经检查过它并没有真正起作用,但我明白了,谢谢,我将对您的答案进行一些小改动并接受它。谢谢
  • @Madiyor 我认为你最好使用像django-mptt 这样的第三方库来实现Category,它为tree 之类的对象实现了复杂的数据结构,这样的递归非常低效
  • 在这种情况下,我认为你不会有单个对象检索/创建的问题,但你可能会遇到复杂过滤的问题,这会导致单个操作中的许多查询,mptt 使用nested set 和其他一些数据结构来实现关系数据库中的树。因此您可以在单个查询中完成大部分任务,值得一看 imo。
猜你喜欢
  • 1970-01-01
  • 2020-02-12
  • 2018-02-24
  • 2012-06-01
  • 2016-07-29
  • 2023-04-03
  • 1970-01-01
  • 2019-10-26
相关资源
最近更新 更多