So, I have two applications that I want to link together in a many-to-many relationship in my project.
The first application is described by the following model.
model.py:
class ChannelCategory(models.Model):
name = models.CharField(max_length=200, db_index=True)
def __str__(self):
return '%s' % self.name
class Channel(models.Model):
category = models.ForeignKey(ChannelCategory, on_delete=models.CASCADE)
name = models.CharField(max_length=200, db_index=True)
class Meta:
ordering = ['category']
def __str__(self):
return '%s (%s)' % (self.category, self.name)
The second application is described by the following model
class Tariff(models.Model):
channels_list = models.ManyToManyField(Channel, blank=True, db_index=True, symmetrical=False)
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_objects(self):
return ([str(p.name) for p in self.channels_list.all()])
Now what do I want to do? Suppose that the tariff object contains 4 channels, which have different categories, and we get approximately the following picture: tariff A has 4 channels from 2 different channel categories, for example, the "mega" tariff has
['ChannelCategory_1: Channel_1', 'ChannelCategory_1: Channel_3', 'ChannelCategory_2: Channel_2', 'ChannelCategory_2: Channel_4']
I do not understand how to display information on the interface correctly. I need to get this kind of information on my template:
['ChannelCategory_1: 'Channel_1', 'Channel_3'']
['ChannelCategory_2: 'Channel_2', 'Channel_4'']
I will be glad for any help, thanks in advance!
UPDATED
Why 'QuerySet' object has no attribute 'channels_list' in?
tariff = Tariff.objects.prefetch_related('channels_list')
category_channel_dict = defaultdict(list)
for channel in tariff.channels_list.all():
category_channel_dict[channel.category.name].append(channel.name)
It worked. I don't know how it looks nice or not, but inside in the class Tariff, you need to describe the function get_channels:
from itertools import groupby
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)
Thus, we will get the following channel_list (an example of what is pulled from my database processed by this function):
ChannelCategory_1: ChannelName_1; ChannelName_2; ChannelName_3; ChannelName_4.
ChannelCategory_2: ChannelName_5; ChannelName_6.
ChannelCategory_3: ChannelName_6 etc.