Frank
Frank

Reputation: 2837

'ManyToManyField' queries

I'm advancing with the web app I asked about earlier.

Currently, my models.py is

from django.db import models
from unittest.util import _MAX_LENGTH

class Alimento(models.Model):
    INTOLERANCIAS = (
        ('00', 'Ninguna'),
        ('GL', 'Gluten'),
        ('CR', 'Crustáceos'),
        ('HU', 'Huevos'),
        ('FS', 'Frutos Secos'),
        ('AP', 'Apio'),
        ('MO', 'Mostaza'),
        ('SE', 'Sésamo'),
        ('PE', 'Pescado'),
        ('CA', 'Cacahuetes'),
        ('SO', 'Sulfitos'),
        ('SJ', 'Soja'),
        ('LA', 'Lácteos'),
        ('AL', 'Altramuz'),
        ('ML', 'Moluscos'),
        ('CA', 'Cacao'),


    )
    nombre = models.CharField(max_length=60)
    intolerancia = models.CharField(max_length=2, choices=INTOLERANCIAS)

    def __str__(self):
        return self.nombre


class Receta(models.Model):
    nombre = models.CharField(max_length=100)
    raciones = models.IntegerField(default=1)
    preparacion = models.TextField(default='')
    consejos = models.TextField(blank=True)
    ingredientes = models.ManyToManyField(Alimento, through='Ingrediente', related_name='ingredientes')

    def __str__(self):
        return self.nombre

    def getIntolerancias(self):
        ing = self.ingredientes.all()
        intolerancias = []
        for i in ing:
            alimentos = i.alimento.all()
            for a in alimentos:
                intolerancias.append(a.get_intolerancia_display()) 

        return intolerancias



class Ingrediente(models.Model):
    receta = models.ForeignKey('recetas.Receta', on_delete=models.CASCADE)
    alimento = models.ManyToManyField(Alimento)
    cantidad = models.FloatField(default=0)
    descripcion = models.CharField(max_length=60, blank=True)

    def __str__(self):
        return self.alimento.__str__()

the method getIntolerancias is supposed to list the food intolerances related to each of the ingredients of a given recipe (Receta). To do that, I try to get the queryset of ingredients (Ingrediente) with ing = self.ingredientes, but when I try it on shell I get this error message

Traceback (most recent call last):   File "/usr/lib/python3.5/code.py", line 91, in runcode
    exec(code, self.locals)   File "<console>", line 1, in <module>   File "/usr/local/lib/python3.5/dist-packages/django/db/models/fields/related_descriptors.py", line 476, in __get__
    return self.related_manager_cls(instance)   File "/usr/local/lib/python3.5/dist-packages/django/db/models/fields/related_descriptors.py", line 758, in __init__
    self.target_field_name = rel.field.m2m_reverse_field_name()   File "/usr/local/lib/python3.5/dist-packages/django/utils/functional.py", line 15, in _curried
    return _curried_func(*(args + moreargs), **dict(kwargs, **morekwargs))   File "/usr/local/lib/python3.5/dist-packages/django/db/models/fields/related.py", line 1504, in _get_m2m_reverse_attr
    return getattr(self, cache_attr) AttributeError: 'ManyToManyField' object has no attribute '_m2m_reverse_name_cache'

I've searched for the error, but the answers I've found don't seem to have what I need (I may just don't understand enough to see it does?)

UPDATE

When I run this on the shell I do

g = Receta.objects.get(nombre = 'Gazpacho')
g.getIntolerancias()

I get an error

intolerancias.append(a.get_intolerancia_display()) AttributeError: 'Ingrediente' object has no attribute 'get_intolerancia_display'

However, if I iterate and get the first element of g.ingredientes.all() and call get_intolerancia_display() it does work OK

a = g.ingredientes.all().first()
a.get_intolerancia_display()
'Gluten'

Upvotes: 0

Views: 493

Answers (1)

Wilfried
Wilfried

Reputation: 1633

Update after comments:

Documentation about Many-to-many relation

def get_intolerancias(self):
        alimentos = self.ingredientes.all() # Give us all alimento of a recetta
        intolerancias = []
        for a in alimentos:
            intolerancias.append(a.get_intolerancia_display())            
        return intolerancias

Upvotes: 1

Related Questions