Django模型中的范畴聚类

2024-06-06 00:33:01 发布

您现在位置:Python中文网/ 问答频道 /正文

上下文:创建CMS

我正在寻找一种有效的方法来表示Django模型中文章的主题嵌套/依赖性。现在,类别定义如下:

class Category(models.Model):
    parent        = models.ForeignKey('self', default=None, null=True, blank=True, related_name='nested_category', on_delete=models.CASCADE)
    name          = models.CharField(max_length=50, unique=True)
    nesting_level = models.IntegerField(default = 0, editable=False)

    def __init__(self, *args, **kwargs): 
        super(Category, self).__init__(*args, **kwargs)
        if self.parent != None:
            self.nesting_level = self.parent.nesting_level + 1
        elif self.parent == None:
            self.nesting_level = 0

    def __str__(self):                           
        full_path = [self.name.lower()]                                        
        k = self.parent                          

        while k is not None:
            full_path.append(k.name.lower())
            k = k.parent

        return '->'.join(full_path[::-1])

这很管用。每次添加一个类别时,nesting_level都是基于父级的nesting_level计算的。我看到了BDD中的变化(我知道,不应该重写Django中的__init__,但我稍后会讨论这个问题)。你知道吗

需求

假设我有以下第三类:

Code--------Python---------Django
 [1]    |     [2]     |      [3]
        |             |----Functional_Programing
        |---Java               [5]
             [4]

当点击类别Python时,视图不应该只在

  • code->python但是
  • code->python->django
  • code->python->functional_programing

因为后者也与python相关。当点击url /browse/code->python/时,视图会显示类似articles = Article.objects.filter(category__in=[2, 3, 5])

这个想法行不通(我也不知道为什么)

由于类别不经常更改,我认为最好在BDD本身中表示这三种结构,以便轻松提取儿童主题列表。桌子看起来像:

id | name                  | nesting_level | cluster | parent
1  | Code                  | 0             | 1,2,3,5 | None
2  | Python                | 1             | 2,3,5   | 1
3  | Django                | 2             | 3       | 2
4  | Java                  | 1             | 4       | 1
5  | Functional_programing | 3             | 5       | 2

类别类,稍作修改:

class Category(models.Model):
    parent        = models.ForeignKey('self', default=None, null=True, blank=True, related_name='nested_category', on_delete=models.CASCADE)
    name          = models.CharField(max_length=50, unique=True)
    nesting_level = models.IntegerField(default = 0, editable=False)
    cluster       = models.CharField(default = "", max_length=20, editable=False)

    def __init__(self, *args, **kwargs): 
        super(Category, self).__init__(*args, **kwargs)

        self.cluster = str(self.id)
        if self.parent != None:
            self.nesting_level = self.parent.nesting_level + 1
            self.parent.cluster = "{},{}".format(self.parent.cluster,self.id)
        elif self.parent == None:
            self.nesting_level = 0

它似乎在Iprint时起作用,但在BDD中似乎没有附加更改(在开发的早期阶段:一个SLQlite)。我读到__init__不应该在Django中被重写,因为相关的“信号原因”,所以我也尝试重写save

def save(self, *args, **kwargs):
        self.cluster = str(self.id)
        if self.parent != None:
            self.nesting_level = self.parent.nesting_level + 1
            self.parent.cluster = "{},{}".format(self.parent.cluster,self.id)
        elif self.parent == None:
            self.nesting_level = 0
        super(Category, self).save(*args, **kwargs)

这也不起作用,但这次,因为self.id=None(<class 'NoneType'>)。你知道吗

我开始觉得有点迷失在这个ORM的微妙之处。因为可能有更直接的方法来实现我想要的目标,但我也有兴趣了解为什么我的方法不起作用,欢迎提供各种建议。你知道吗


Tags: djangonameselfnoneidtrueinitmodels