0

I have 4 models.. let's say:

Modal BigBox:
   small_boxes = ManyToMany
   .....

Model SmallBox
   .....

Model Item
   .....

Model Big_box_small_box_items:
   big_box = fk(BigBox)
   small_box = fk(SmallBox)
   Item = fk(Item)
   .....

In my template I want to go to a template for a big box and see a list of items in each small box. I have a working page now but it involves lost of nesting logic inside the view and an inefficient number of database hits.

My head is swimming a bit as a hobbyist and I would appreciate any pointers.

Matt Schucker
  • 37
  • 1
  • 6

2 Answers2

0

In your template you should be able to do something like:

{% for smallbox in bigbox.smallboxes.all %}
{{ smallbox.some_attribute }}<br>
{% endfor %}

Similar question here: https://stackoverflow.com/a/40569127/4872140

Note that with the many to many, you don't use _set on smallboxes as you would for a normal foreign key relationship.

INCORRECT: (don't do this)

{% for smallbox in bigbox.smallboxes_set.all %}
{{ smallbox.some_attribute }}<br>
{% endfor %}

There is some discussion on how to use/why the .all method call works in the Django Template Language documentation. More specifically, on the ManyToMany handling.

EDIT: After reading your comment, I see you have a slightly different issue than I originally read. I think you may need to add another loop inside of the outer loop. It is a little tough here due to the missing details in the models in the post. I'm going to suggest you rename Big_box_small_box_items to BigBoxSmallBoxItems, and rename the field from Item to item. Review the coding style and stick with it to save yourself some headaches later (https://docs.djangoproject.com/en/dev/internals/contributing/writing-code/coding-style/#model-style)

{% for smallbox in bigbox.smallboxes.all %}
    {% for sbitem in smallbox.bigboxsmallboxitems_set.all %}
         {{ sbitem.item.your_item_attribute }}<br>
    {% endfor %}
{% endfor %}

I doubt this will optimize your queries, and you may end up keeping what you've got. Depending on what you've already got in your view you may wish to review the prefetch_related tool (https://docs.djangoproject.com/en/dev/ref/models/querysets/#prefetch-related)

AMG
  • 1,606
  • 1
  • 14
  • 25
  • Thanks for your time! I don't see how the given example would display the items in each small box. The given link is helpful. I appreciate it! – Matt Schucker Jul 26 '23 at 14:24
0

I ended up creating a list in my view and reduced database hits from 85 down to 10...

When given a big box..

    big_box_small_boxes = small_box.objects.filter(big_box=big_box)
    big_box_small_boxes_dict = {}
    big_box_list = []
    for small_box in big_box_small_boxes:
        big_box_item_dict = {
            "small_box" : small_box.name,
            "big_box_items" : Big_box_small_box_items.objects.filter(big_box=big_box, small_box=small_box).prefetch_related('item')
        }
        big_box_list.append(big_box_small_boxes_dict)

and then in the template...

{% for item in big_box_list %}
   {item.small_box}
   {% for big_box_item in item.big_box_items %}
      {% big_box_item.item.name %}
   {% endfor %}
{% endfor%}

Matt Schucker
  • 37
  • 1
  • 6