penk
penk

Reputation: 279

Access many to many field from queryset Django

I have two models:

class Vineyard(models.Model):
    name = models.CharField(max_length=255, blank=True)

    def __str__(self):
        return self.name


class WineRegion(models.Model):
    name = models.CharField(max_length=255)
    vineyards = models.ManyToManyField(Vineyard, blank=True)

    def __str__(self):
        return self.name

And I want to access all vineyards from the wine region. Here is what I've tried:

if len(id_list) > 0:
    wr = WineRegion.objects.filter(id__in=id_list)
    vineyardList = wr.vineyards.all()

But it gives me an error ---> AttributeError: 'QuerySet' object has no attribute 'vineyards'

How can I solve this?

EDIT:

And what if I have another model called Country? Here is the model:

class Country(models.Model):
    name = models.CharField(max_length=255)
    wine_rg = models.ManyToManyField(WineRegion, blank=True)

    def __str__(self):
        return self.name

I want to access all vineyards from the wine region, but now I have a list of Country IDs. How can I solve this?

I can do something like this:

wine_region_id = Country.objects.filter(id__in=country).distinct().values('wine_rg')
vineyardList = vineyardList.filter(wineregion__in=wine_region_id)

But I'm curious is there any better method to do something like this?

Upvotes: 1

Views: 62

Answers (1)

Brian Destura
Brian Destura

Reputation: 12078

Since wr is a list of WineRegions, you need to iterate through them first:

vineyardList = []
for wr in WineRegion.objects.filter(id__in=id_list):
    for vineyard in wr.vineyards.all():
        vineyardList.append(vineyard)

But this will hit your db multiple times just to get each vineyard objects. Instead, you can access the related name wineregion from Vineyard to get all the vineyard objects in one query like this:

vineyardList = Vineyard.objects.filter(wineregion__in=WineRegion.objects.filter(id__in=id_list))

or simply:

vineyardList = Vineyard.objects.filter(wineregion__in=id_list)

Upvotes: 1

Related Questions