0

Suppose that I have models like these:

models.py

class Category(models.Model):
    name = models.CharField(max_length=70, verbose_name='Name')
    order_num = models.IntegerField(verbose_name='Order Number')

class Advertisement_Type(models.Model):
    name = models.CharField(max_length=70, verbose_name='Name')
    ad_category = models.ManyToManyField(Category, verbose_name='Ad Category')

class Advertisement(models.Model):
    title = models.CharField(max_length=70, verbose_name='Title')    
    ad_type = models.ForeignKey(Advertisement_Type, on_delete=models.CASCADE, verbose_name='Advertisement Type')

How can I retrieve advertisement by category and advertisement type in such format by using filters only? Is this possible? Because the only way I can think of is querying everything and then building the dictionary/JSON manually through a number of for-loops and if-else which I would like to avoid.

Expected format/output

advertisement_type: {
    name: 'Type 1',
    category: {'Health', 'Engineering'},
    advertisement: {ads1, ads2, ads3}, # Can these be objects?
},
advertisement_type: {
    name: 'Type 2',
    category: {'Math', 'Numbers'},
    advertisement: {ads4, ads5, ads6}, # Can these be objects?
}

Thank you!

Paolo
  • 823
  • 6
  • 18

1 Answers1

0

To get related objects of a model you can use prefetch_related which can work with ManyToMany relations.

In the example ads_types, ad_category, advertisement_set are QuerySets, so they return a list of objects and can be filtered as well.

ads_types = Advertisement_Type.objects.prefetch_related('ad_category', 'advertisement_set')

res = []
for adt in ads_type:
  res.append({
    "name": adt.name,
    "category": adt.ad_category.values_list('name', flat=True),
    "advertisement": adt.advertisement_set.values_list('title', flat=True),
  })

Or you can check Django Rest Framework serializers for related objects to get json object representation along with relations.

You might also improve ManyToMany field by adding related_name option.

Oleg Russkin
  • 4,234
  • 1
  • 8
  • 20