Search code examples
pythondjangodjango-modelsdjango-managers

Getting items in model referenced by a onetoonemodel in django


I have this database layout

class Clinic(models.Model):


class Menu(models.Model):
    ...
    menu = models.OneToOneField(Clinic, related_name='menu')


class Item(models.Model):
    ...
    menu = models.ForeignKey('Menu')

and I would like to access my Menu model and the Items linked to that menu from my Clinic model.

I have tried this

In [5]: clinic = Clinic.objects.get(pk=1)

    In [12]: clinic.menu
Out[12]: <Menu: Menu object>

In [13]: clinic.menu.objects.all()
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-13-2aff8882b6ad> in <module>()
----> 1 clinic.menu.objects.all()

/Users/gabriel/.virtualenvs/meed_waps/lib/python3.4/site-packages/django/db/models/manager.py in __get__(self, instance, type)
    253     def __get__(self, instance, type=None):
    254         if instance is not None:
--> 255             raise AttributeError("Manager isn't accessible via %s instances" % type.__name__)
    256         return self.manager
    257 

AttributeError: Manager isn't accessible via Menu instances

but it tells me that the manager can't access it. Conceptually it seems like I should be able to access the items and get a list by tracing the relationship down through the clinic model like this Clinic > Menu > Items. Is there another way I should be doing this?


Solution

  • clinic.menu.objects is the ModelManager for the Menu model - note that it's an attribute of the Menu class, not of your clinic.menu instance. ModelManager classes are used to query the underlying table, and are not supposed to be called directly from instances (which wouldn't make much sense anyway), hence the error message.

    Conceptually it seems like I should be able to access the items and get a list by tracing the relationship down through the clinic model like this Clinic > Menu > Items

    That's indeed possible (hopefully), but where are you mentionning items in clinic.menu.objects ? You want clinic.menu.item_set.all().