контекст: создание 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 (я знаю, что не нужно переопределять __init__
в Django, но я вернусь к этому вопросу позже).
Необходимость
Скажите, у меня есть следующееКатегория три:
Code--------Python---------Django
[1] | [2] | [3]
| |----Functional_Programing
|---Java [5]
[4]
При попадании в категорию Python , представление должно не только представлять Статьи в
code->python
но также code->python->django
code->python->functional_programing
, поскольку последние также связаны с питоном .При переходе по 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
Кажется, работает, когда я print
, но изменения делаюткажется, не добавляются в 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.Поскольку, вероятно, есть более простые способы достижения того, что я ищу, но мне также интересно понять, почему мой подход не работает, приветствуются всевозможные советы .