Django запрос отношения ManyToMany из parent=ForeignKey('self')

Это для проекта блога на Django. У меня есть модель 'Profile' и 'TechStackCategory', где они имеют отношения ManyToMany. Profile - это профиль пользователя для блога. TechStackCategory имеет категории стеков пользователя, которые он знает.

Пример моделиTechStackCategory: Languages, Languages -> Python, Languages -> Java, Frameworks, Frameworks -> Django

class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
image = models.ImageField(default='default.jpg', upload_to='profile_pics')
background_image = models.ImageField(upload_to='profile_background_pics', blank=True, null=True,)
bio = models.CharField(max_length=200, help_text="200 characters or less")
tech_stack_cat = models.ManyToManyField('TechStackCategory', blank=True)

def __str__(self):
    return f"{self.user.username}'s profile"

class TechStackCategory(models.Model):
parent = models.ForeignKey('self', related_name='children', on_delete=models.CASCADE, blank=True, null=True)
title = models.CharField(max_length=50, unique=True)

def __str__(self):
    return f"{self.title}"

class Meta:
    #enforcing that there can not be two categories under a parent with same slug

    # __str__ method elaborated later in post.  use __unicode__ in place of

    unique_together = ('title', 'parent',)    
    verbose_name_plural = "categories"     

def __str__(self):                           
    full_path = [self.title]                  
    k = self.parent
    while k is not None:
        full_path.append(k.title)
        k = k.parent
    return ' -> '.join(full_path[::-1])  

Поэтому я следую примеру из этого поста https://dev.to/shivamrohilla/how-to-make-a-sub-and-sub-sub-categories-in-django-most-important-216p

Дело в том, что пример в посте показывает все родительские и дочерние объекты из модели Category. Он отфильтровывает запрос в представлениях как catg = Category.objects.filter(parent=None), который возвращает <QuerySet [<TechStackCat: Languages>, <TechStackCat: Frameworks>]>

Я хотел бы сделать то же самое, но добавить дополнительный фильтр, чтобы отфильтровать категории пользователя.

views.py
def get_context_data(self, *args, **kwargs):
user = self.request.user
catg = TechStackCategory.objects.filter(profile__user=user).all().filter(parent=None)
context ['catg'] = catg

прямо сейчас это возвращает пустоту, так что это не работает. <QuerySet []>

и TechStackCat.objects.filter(profile__user=user).all() возвращает <QuerySet [<TechStackCat: Languages -> Python>, <TechStackCat: Languages -> Java>]>

чтобы следовать примеру из постов, мне нужно захватить родительский объект.

enter image description here

Или другой вариант для меня - я могу выполнить ниже, чтобы у меня не было дублирующихся родителей. (Например: Languages, Languages, Languages -> Python, Languages -> Java) Мне просто нужно показать ([Languages -> Python, Java],[Frameworks -> Django])

parent_list = []
catg = TechStackCategory.objects.filter(profile__user=user).all()
for c in catg:
    if c.parent not in parent_list:
        parent_list.append(c.parent)

но я думаю, что лучший способ справиться с этим - заставить TechStackCategory.objects.filter(profile__user=user).all().filter(parent=None) работать

извините, я знаю, что это беспорядочно... Ваша помощь будет оценена по достоинству...

edit--

Итак, в моей панели администратора (модель профиля) я выбрал следующее:

enter image description here

Есть ли способ автоматически захватить родительский объект (Languages), просто выбрав (Languages -> Python)

edit--

Итак, я выбрал родительский объект (Languages) в панели администратора, и он отображается так, как я хочу...

enter image description here

но мне интересно, есть ли способ захватить родительский объект (Languages) просто при выборе (Languages -> Python)

В принципе, в том, что вы написали, нет ничего плохого, хотя формат немного не тот. Фильтр может быть одним оператором, а вызов all() является излишним:

TechStackCategory.objects.filter(profile__user=user, parent=None)

Вы сказали, что набор запросов, который создается только из фильтра профиля, выглядит следующим образом:

и TechStackCat.objects.filter(profile__user=user).all() возвращает <QuerySet [<TechStackCat: Языки -> Python>, <TechStackCat: Языки -> Java>]>

.

Это будут два объекта, которые оба имеют Languages в качестве родительских объектов, и оба не пройдут фильтр parent=None. Набор запросов также не возвращает саму категорию Languages, предположительно потому, что она не связана с пользователем. Таким образом, у вас нет объектов, удовлетворяющих обоим условиям: а) связанных с пользователем и б) являющихся конечной родительской категорией.

Вернуться на верх