2

These are my models where Apps have menu_items:

class App(models.Model):
    name = models.CharField(max_length=50)

class Menu(models.Model):
    name = models.CharField(max_length=120)
    app = models.ForeignKey(App, on_delete=models.PROTECT)
    url = models.CharField(max_length=120, null=True)

    class Meta:
        ordering = ['name', 'app']

This is my View, is there any way this can be optimized?

class AboutView(TemplateView):
    template_name = 'about.html'

    def get_context_data(self, *args, **kwargs):
        context = super(AboutView, self).get_context_data(*args, **kwargs)
        menu_items = Access.objects.filter(user__id=self.request.user.id)
        applist = []
        for m in menu_items:
            applist.append(m.menu.app.name)
        apps = App.objects.filter(name__in=applist)
        context = {
            "menu_items": menu_items,
            "apps": apps
        }
        return context

This is my template, I rearrange the menu_items under each app.

<ul class="navbar-nav ml-auto">
                {% for app in apps %}
                    <li class="nav-item dropdown">
                        <a class="nav-link" href="#" id="appMenu" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                            {{ app.name }}
                        </a>
                        <div class="dropdown-menu dropdown-menu-left" aria-labelledby="appMenu">
                            {% for item in menu_items %}
                                {% if item.menu.app.name == app.name %}
                                    <a class="dropdown-item" href="{{ item.menu.url }}">{{ item.menu.name }}</a>
                                    {# href="{{ item.menu.url }} #}
                                {% endif %}
                            {% endfor %}
                        </div>
                    </li>
                {% endfor %}
            </ul>

I was hoping there was a better way in doing this. Thank you in advance. As requested, here is the Access Model

class Access(models.Model):
    menu = models.ForeignKey(Menu, on_delete=models.PROTECT)
    user = models.ForeignKey(User, on_delete=models.PROTECT)

2 Answers2

1

I'm not going to write a full-blown answer, because I don't have enough time and couldn't test the code right now. But anyway: the features you're looking for are:

Combining all those features should solve your problem. The only caveat is the filtering of menu items with the Prefetch object which I have never used so far so I can't say for sure if it will work as expected.

bruno desthuilliers
  • 75,974
  • 6
  • 88
  • 118
0

This worked in removing the app_list and "for loop"

apps = App.objects.filter(menu__name=F('menu'))

@bruno desthuilliers, I am still trying to understand prefetch