Linbreux
Linbreux

Reputation: 65

How can I filter manytomany models?

I would like to filter my plots objects on the fruit ex.pear. The Inputs are linked via a manytomany to the plots. This is the structure: foto

This is the data I get out of it: foto2

What i would like to have: foto3

result:

foto4

I tried the following:

plots = Plot.objects.filter(fruittype__fruit="Pear")
inputs = Input.objects.filter(plot__in=plots).distinct()

This gives me already a close solution for my problem but not what I want. last

Now I only would like to filter out the other plots that still show up with apple.

models inputs:

class Product (models.Model):
    type = models.ForeignKey(Type, on_delete=models.CASCADE)
    product = models.CharField(max_length=70)
    standaard_dosis = models.FloatField()

    def __str__(self):
        return self.product
class Input (models.Model):
    datum = models.DateField()
    plot = models.ManyToManyField(Plot)

    def __str__(self):
        return str(self.datum)

class ProductInputs (models.Model):
    input = models.ForeignKey(Inputs, on_delete=models.CASCADE, default="")
    product = models.ForeignKey(Product, on_delete=models.CASCADE, default="")
    dosis = models.FloatField()

    def __str__(self):
        string = str(self.product)
        return string

models plots:

class Fruit(models.Model):
    fruit = models.CharField(max_length=30, primary_key=True)

    def __str__(self):
        return self.fruit

    class Meta:
        verbose_name_plural = "fruits"


class Fruittype(models.Model):
    fruit = models.ForeignKey(Fruit, on_delete=models.CASCADE)
    fruittype = models.CharField(max_length=30, primary_key=True)

    def __str__(self):
        return self.fruittype

    class Meta:
        verbose_name_plural = "fruitypes"


class Plot(models.Model):
    name = models.CharField(max_length=30)
    fruittype = models.ForeignKey(Fruittype, on_delete=models.CASCADE)

    def __str__(self):
        return str(self.fruittype.fruit) + " | " + self.name

    class Meta:
        verbose_name_plural = "plots"

Upvotes: 1

Views: 211

Answers (2)

Linbreux
Linbreux

Reputation: 65

It worked with:

all_inputs=Input.objects.filter(plot__pk__in=plot_ids).distinct().prefetch_related(Prefetch('plot', queryset=Plot.objects.filter(fruittype__fruit__fruit="Pear")))

Upvotes: 1

Higor Rossato
Higor Rossato

Reputation: 2046

Your Plot queryset is not going as deep as it should. I think you should change to something like this (although this is it's a bit of overkill)

plot_ids = Plot.objects.filter(fruittype__fruit__fruit="Pear").values_list('pk', flat=True)

or

plot_ids = Plot.objects.filter(fruittype__fruittype="Pear").values_list('pk', flat=True) # I don't know what fruittype is but I guess this would help you

Then your "inputs"

inputs = Input.objects.filter(plot__pk__in=plot_ids).distinct()

You might wanna try this as well:

from django.db.models import Prefetch
Input.objects.prefetch_related(
    Prefetch('plot', queryset=Plot.objects.filter(fruittype__fruit__fruit="Pear"))
)

Upvotes: 1

Related Questions