I have problems with the menu not showing when included. Can you see what’s going wrong?
If I select this url: ‘http://127.0.0.1:8000/menu/’ the menu is displayed and the menu items are showing.
I have this structure:
#base.html:
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Shifts</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js" integrity="sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN" crossorigin="anonymous"></script>
<script src="https://kit.fontawesome.com/2472b08078.js" crossorigin="anonymous"></script>
<link href="{% static 'css/shifts.css' %}" rel="stylesheet" type="text/css">
<link rel="shortcut icon" type="image/png" href="{% static 'favicon.ico' %}"/>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.47/css/bootstrap-datetimepicker.min.css">
<!-- Additional CSS block for child templates -->
{% block additional_css %}{% endblock %}
{% include "shifts-scripts.html" %}
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>
Page where I include the menu:
#shift-layout.html:
{% extends 'base.html' %}
{% block content %}
{% load static %}
{% include "menu.html" %}
<div class="m20"><!--START PAGE-->
<p>Admin new</p>
{% for week in weeks %}
<div class="weeknr">
<h1>Week {{ week.week_number }}</h1>
<!--rest of my html-->
This is the view:
def menu_view(request):
menu_items = MenuItem.objects.all()
context = {
'menu_items': menu_items,
# Add other context data if required
}
return render(request, 'menu.html', context)
This is the path:
path('menu/', menu_view, name='menu'),
Including a template does not execute any view - it simply includes that template text into the template currently being rendered. (A view is not directly associated with any template - the relationship works in the other direction. Views use templates, views aren’t referenced by templates.)
The general mechanism for adding a menu on every page is to use a custom context processor to add the menu data to the context of every page being rendered.
Great teaching Ken! Thanks. Works now! There is a first time for everything.
I tried to add different menu’s for different user groups. Is this the correct approach? Only the Admin menu is showing. The group names are retrieved correctly by the print debug code added. Where do I go wrong?
# context_processors.py
from django.contrib.auth.models import Group
def menu_items(request):
if request.user.is_authenticated:
user_groups = Group.objects.filter(user=request.user).values_list('name', flat=True)
print("User groups:", user_groups)
if 'Admin' in user_groups:
print("User groups:", user_groups)
menu_data = [
{'name': 'Home', 'url': '/'},
{'name': 'Profile', 'url': '/profile/'},
{'name': 'Orders', 'url': '/orders/'},
{'name': 'AdminMenu', 'url': '/'}
# Add more menu items for customers
]
elif 'Customer' in user_groups:
print("User groups:", user_groups)
menu_data = [
{'name': 'Home', 'url': '/'},
{'name': 'Profile', 'url': '/profile/'},
{'name': 'CustomerMenu', 'url': '/'}
# Add more menu items for regular users
]
elif 'User' in user_groups:
print("User groups:", user_groups)
menu_data = [
{'name': 'Home', 'url': '/'},
{'name': 'Profile', 'url': '/profile/'},
{'name': 'UserMenu', 'url': '/'}
# Add more menu items for regular users
]
else:
# Default menu for authenticated users without any specific group
menu_data = [
{'name': 'Home', 'url': '/'},
{'name': 'About', 'url': '/about/'},
{'name': 'Contact', 'url': '/contact/'},
{'name': 'ElseMenu', 'url': '/'}
# Add more default menu items as needed
]
else:
# Menu for anonymous users
menu_data = [
{'name': 'Home', 'url': '/'},
{'name': 'About', 'url': '/about/'},
{'name': 'Contact', 'url': '/contact/'},
# Add more menu items for anonymous users
]
return {'menu': menu_data}
What specifically is happening for other Users? What are they seeing?
What is the output you’re seeing from your print statement?
Keep in mind that the way you have this coded, if a person is a member of multiple groups, they’re going to get the first menu in line that they encounter. Someone who is a member of both “Customer” and “User” is only going to get the “Customer” menu.
In case of a user logged in I get 2 times printed te correct name EG ‘User’
User groups: <QuerySet [‘User’]>
User groups: <QuerySet [‘User’]>
Displays only ‘Logout’ in the menu, no other menu items, as expected using this code in the template:
{% for item in menu %}
<li><a class="nav-link" href="{{ item.url }}">{{ item.name }}</a></li>
{% endfor %}
{% if user.is_authenticated %}
<li><a class="nav-link" href="{% url 'logout' %}">Logout</a></li>
{% else %}
<li><a class="nav-link" href="{% url 'login' %}">Login</a></li>
{% endif %}
Superuser get’s:
User groups: <QuerySet [‘Admin’, ‘Customer’, ‘User’]>
User groups: <QuerySet [‘Admin’, ‘Customer’, ‘User’]>
And then the ‘Admin’ menu version is displayed (not the 2 others)
For now I won’t have Admin, Customer or User using more than one group. They all should have their own menu. The menu items are just samples for now. With each have a recognizable value with the menu name.
SORRY!! My Wrong. I forgot to update the User and Customer template with the new content_processor code. It is working fine now.