Answer the question
In order to leave comments, you need to log in
How to extract objects from a many-to-many relationship after filtering them by foreignkey?
Good afternoon! I have a problem that I can't solve, but the answer lies somewhere close. I really hope you can help me here. So, I have the first model , which describes the TV channels channels/models.py (I'll be brief, I won't show too much):
class ChannelCategory(models.Model):
name = models.CharField(max_length=200, db_index=True, verbose_name='Наименование категории канала',
help_text='Например, "Федеральные каналы", "Детские каналы", "Спорт" и т.д.')
slug = models.SlugField(max_length=200, db_index=True, unique=True, verbose_name='Уникальная строка')
def __str__(self):
return '%s' % self.name
class Channel(models.Model):
category = models.ForeignKey(ChannelCategory, on_delete=models.CASCADE, verbose_name='Категория канала')
name = models.CharField(max_length=200, db_index=True, verbose_name='Наименование канала')
class Meta:
ordering = ['category']
def __str__(self):
return '%s (%s)' % (self.name, self.category)
from channels.models import Channel, ChannelCategory
class Tariff(models.Model):
name = models.CharField(max_length=200, db_index=True, verbose_name='Наименование тарифа',
help_text='Укажите наименование тарифа (поле обязательное)')
slug = models.SlugField(max_length=200, db_index=True, verbose_name='Уникальная строка',)
channels_list = models.ManyToManyField(Channel, blank=True, db_index=True, symmetrical=False,
verbose_name='Список каналов')
class Meta:
verbose_name = 'Тариф'
verbose_name_plural = 'Тарифы'
def __str__(self):
return '%s' % self.name
def get_channels_categories(self):
return ([str(p.category) for p in self.channels_list.all()])
def get_channels(self):
pp = [str(p.category) for p in self.channels_list.all()]
return (OrderedDict.fromkeys(pp))
def get_channels_objects(self):
return ([str(p.name) for p in self.channels_list.all()])
from collections import defaultdict
tariff = Tariff.objects.prefetch_related('channels_list').filter(id=1)
category_channel_dict = defaultdict(list)
for channel in tariff.channels_list.all():
category_channel_dict[channel.category.name].append(channel.name)
Answer the question
In order to leave comments, you need to log in
Hooray, it worked. I don’t know how beautiful it looks or not, but inside the Tariff class, you need to describe the function:
def get_channels(self):
channels = list(str(p).split(':') for p in self.channels_list.all())
channel_list = []
for category, name in groupby(channels, lambda x: x[0]):
channels_list_by_group = ";".join([channel[1] for channel in name])
channels_list_by_category = (category + ":" + channels_list_by_group + ".")
print(channels_list_by_category)
channel_list.append(channels_list_by_category)
return ''.join(channel_list)
Yes, you can pull out the channels, but you can already have groups from the channel
>>> from core.models import *
>>> t1 = Tariff.objects.get(pk=1)
>>> t1.channels_list
<django.db.models.fields.related_descriptors.create_forward_many_to_many_manager.<locals>.ManyRelatedManager object at 0x000002C0AA1D7580>
>>> t1.channels_list.all()
<QuerySet [<Channel: Первый канал (Основная)>, <Channel: Второй канал (Основная)>]>
>>>
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question