Make clicked tab active in Bootstrap - django

I am using Django and integrated Bootstrap with Django. Here is my HTML code for the navigation bar:
<div class="navbar navbar-default navbar-fixed-top" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Project name</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li class="active">Home</li>
<li >About</li>
<li>Contact</li>
<li class="dropdown">
Games <span class="caret"></span>
<ul class="dropdown-menu" role="menu">
<li>RacingDNA</li>
<li>Skater Game</li>
</ul>
</li>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
I have written the CSS for an active navigation bar also. Here, only one navigation bar is active. I want to make the clicked navigation bar active and thus apply my CSS. My CSS is working perfect for active navigation bar and for this situation only for one.
I googled and found a solution to add this jQuery:
$('.nav.navbar-nav > li').on('click', function (e) {
e.preventDefault();
$('.nav.navbar-nav > li').removeClass('active');
$(this).addClass('active');
});
Now here is where I am stuck. I don't know where to write this jQuery.
I put this file in the static/js folder and named this code nav-bar.js. However, there is no improvement. Where am I going wrong and where am I making mistakes?

If you dont want to send any additional context from views then you can handle it like this with resolver_match:
<li {% if request.resolver_match.url_name == 'home' %}class="active"{% endif %}>
HOME
</li>
where 'home' is the name given to your url pattern for / (probably '^$') in your urls.py.
So obviously to use this you need to name all your url patterns, which is a good practice anyway.

This solution didn't work when the href attribute of your links will be different from href="#". Why ? Simply because each click on a link triggers a request to the server. In your JS code, you add the method preventDefault() in order to avoid this basic behavior, but I think that not really your objective for this purpose, isn't it ?
To handle this kind of feature you can update your template code by adding something like this :
base.html
<div class="collapse navbar-collapse" id="tn-navbar-collapse">
<ul class="nav navbar-nav">
<li class="{% if nbar == 'home' %}active{% endif %}">
HOME
</li>
...
</ul>
</div>
views.py
def your_view(request):
...
return render(request, 'yourtemplate.html', {'nbar': 'home'})
With this way, you don't have to manage this feature with javascript.

Alternative including URL namespaces:
<li class="nav-item {% if request.resolver_match.view_name == 'scores:list' %}active{% endif %}">
<a class="nav-link" href="{% url 'scores:list' %}">Scores</a>
</li>

I recently ran into this problem and tried every solution I could find. Eventually, I came to this. This example assumes the path to this content is yoursite.com/about
Give your link an id.
<li><a id="about" href="#">About</a></li>
var path = $(location).attr('pathname')
var pa = path.split("/")
$('#'+pa[1]).tab('show')

#rphonika has give a nice answer. But if you have many navigation menus then adding template logic in each list item makes the code untidy. Menu items can be assigned a unique id, the id passed in views and active class can be assigned using a one liner javascript code in html itself.
base.html
<ul class="nav navbar-nav navbar-left">
<li><a class="navmenu-a" id="overview" href="{% url 'webapp:overview' %}">Overview</a></li>
<li><a class="navmenu-a" id="plot" href="{% url 'webapp:plot' %}">Plot</a></li>
<li><a class="navmenu-a" id="board" href="{% url 'webapp:board' %}">Board</a></li>
<li><a class="navmenu-a" id="storyboard" href="{% url 'webapp:storyboard' %}">Storyboard</a></li>
<li><a class="navmenu-a" id="freqs" href="{% url 'webapp:freqs' %}">Faq</a></li>
</ul>
.
.
.
<script type="text/javascript">
{% if nmenu %} $("a#{{nmenu}}").addClass("navmenu-a-active") {% endif %}
</script>
views.py
def overview(request):
...
return render(request, 'overview.html', {'nmenu': 'overview'})
def plot(request):
...
return render(request, 'plot.html', {'nmenu': 'plot'})
And so on for other views

I think the easiest solution is JavaScript / CSS:
Anyway, here is the solution using Jquery. Notice n1,n2 classes in html
In base.html
<nav>
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link n1" href="{% url 'polls:dashboard' %}">
<span data-feather="home"></span>
Dashboard
</a>
</li>
<li class="nav-item">
<a class="nav-link n2" href="{% url 'polls:restaurants' %}">
<span data-feather="file"></span>
Restaurants
</a>
</li>
</ul>
</nav>
<script>
$('nav').find('{% block active_link%}{%endblock%}').addClass('active')
</script>
Then in your dashboard template:
{% block active_link %}.n1{%endblock%}
In your restaurants template:
{% block active_link %}.n2{%endblock%}

After adding gamer's JavaScript into your template code_here , you got to make sure you have the similar settings in your CSS file also, in order to make JavaScript work.
.navbar-nav > li.active > a {
color: #d74b4b;
background: transparent;
border-bottom: none;
}

I would rather prefer to only edit the template using rather than editing both views and templates for this. People needing the same, rather than following the accepted answer, may consider the below way:
<ul class="navbar-nav">
<li class="nav-item {% ifequal request.path '/' %} active {% endifequal %}">
<a class="nav-link" href="/">Home</a>
</li>
</ul
You can change 'index' above with your own

You can check if a string is in your URL path. This is helpful for hierarchical or nested URL paths
<li {% if 'home' in request.get_full_path %}class="active"{% endif %}>
HOME
</li>

If you want activate by context you can do like this variable == to context in .views
<li class="nav-item {% ifequal variable context %}active{% endifequal%}">
<a class="nav-link" href="{% url 'scores:list' %}">Scores</a>
</li>

Related

Navbar For Ecommerce Website Using Django

I am designing eCommerce website based on django in backend. I want to create navbar which will contain menu based on categories of products.
I want this Navbar dynamic as whenever new category posted it should automatically appear in menu field. My front end is bootstrap and Html.
Please help me with logic.
Thank You.
this is very general by I try to give you some clue to search forward.
first, think of a navbar something like this:
<nav class="navbar">
product1
product2
.
.
.
</nav>
you can see a pure sub navbar example in this link or you can use bootstrap if you want.
now let's go back to Django templates, you must have something like base.html template file that your navbar code is there and every other template will inherit the navbar from it, then in your views.py for every view just pass the categories that you have already queried from the database to render function:
def view(request):
categories = Category.objects.all()
.
.
.
return render(request, 'some.html',
{
'categories': categories,
.
.
.
}
this will pass all the categories in your database to the base.html template where you can just put it in a {% for %} template tag to inject to HTML:
<nav class="navbar">
{% for catg in categories %}
{{ catg.name }}
{% endfor %}
</nav>
ok, this is not the definite solution, but I think you got the algorithm.
Use bootstrap.it will help you for mobile friendliness.they have a ready made nice navbar for use that you can modify.just download bootstrap examples,get the code for navbar.
design your main/home page as you like.then to stick the nav to other pages,use block content like this:
{% block content %}
code...
code...
{% endblock %}
there are lots of tutorials for extending base html page.pick and watch 'em.
in views.py
def your_view_function(request):
categories = Category.objects.all()
return render(request,'your_template.html',{'categories':categories})
in template
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="#">Navbar</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Categories
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
{% for category in categories %}
<a class="dropdown-item" href="#">{{category.name}}</a>
{% endfor %}
</div>
</li>
</div>
</nav>
Thank You All For Your Answers. I have created dynamic navbar as follows
First I created context_processor.py file in which I imported ProductModel as follows:
I added above file in settings.py
from products.models import ProductModel
def context_prod(request):
allCat=[]
catProd = ProductModel.objects.values("category","id")
cats = {item["category"] for item in catProd}
for cat in cats:
prod = ProductModel.objects.filter(category=cat)
subcat = prod.values("subcategory","id")
subcat = {item["subcategory"] for item in subcat}
allCat.append([prod, subcat])
context={
"allCat": allCat
}
return(context)
Then in navbar.html I added following HTML code
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
{% for prod, subcat in allCat %}
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{{ prod.0.category }}
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
{% for i in subcat %}
<a class="dropdown-item" href="#">{{ i }}</a>
{% endfor %}
</div>
</li>
{% endfor %}
And Bingo..!! It worked

Why I am getting a filter error for my template tag?

I'm not sure why I am getting this filter error. I looked up other peoples similar issues with this, and I am definitely loading my template tag, I restarted the server, I have a template tags folder with an init.py file and the file that holds my tag, so , what am I doing wrong here?
error is at {{ request.user|unread_messages }}, Invalid filter: 'unread_messages'
unread_message_counter.py
from django import template
from dating_app import models
register = template.Library()
#register.simple_tag
def unread_messages(user):
return user.InstantMessage.filter(viewed=False).count()
**base.htmnl **
{% load bootstrap4 %}
{% load unread_messages_counter %}
<!-- Navbar is located in this file -->
<!doctype html>
<html lang="en">
<head>
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
{% block head %}
<title>Basee</title>
{% endblock %}
</head>
<body>
<nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark">
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarsExampleDefault">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="{% url 'dating_app:home' %}">Home <span class="sr-only">(current)</span></a>
</li>
</ul>
<!-- Below is login/registration links and the logic-->
{% if user.is_authenticated %}
Hello, {{ user.username }}
<ul class="mylinks">
<div>
<li>My Profile</li>
<li>log out</li>
<div>
</ul>
<li class="nav-item">
<a class="nav-link" href="{% url 'dating_app:view_matches' user.id %}">Matches</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'dating_app:conversations' user.id %}">Inbox</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'dating_app:mingle' %}">Mingle</a>
</li>
<li class="nav-item">
{{ request.user|unread_messages }}
</li>
{% else %}
<div>
log in
<br>
register
</div>
{% endif %}
This is not a template tag [Django-doc], this is a template filter [Django-doc]. A tag would mean you render this as {% unread_messages … %}. You thus can make it a filter with:
from django import template
from dating_app import models
register = template.Library()
#register.filter
def unread_messages(user):
return user.InstantMessage.filter(viewed=False).count()
Or you can work with a tag, by keeping the #registered.simple_tag, and render this with {% unread_messages request.user %}.
I believe the problem is the name used to load the tag.
Instead of:
{% load unread_messages_counter %}
Try:
{% load unread_messages %}

Django logout button bootstrap navbar

I want to add a logout button to my bootstrap navbar but it doesn't look right.
{# template.html #}
<nav class="navbar navbar-light">
<div class="container">
<div class="navbar-expand">
<ul class="navbar-nav mr-auto">
{% if user.is_authenticated %}
<li class="nav-item">
{{ user.get_username }}
</li>
<form class="form-inline nav-item" action="{% url 'account_logout' %}" method="POST">
{% csrf_token %}
<button type="submit" class="btn btn-info">Log out</button>
</form>
{% else %}
<li class="nav-item">
<a class="nav-link" href="{% url 'account_login' %}">Log in</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'account_signup' %}">Sign up</a>
</li>
{% endif %}
</ul>
</div>
</div>
</nav>
is there any way to make the button look like a bootstrap nav-link ? If not, how do I make it an anchor that will POST to Django's logout endpoint?
This should work
<li class="nav-item">
<a class="nav-link" href="#"
onClick="document.getElementById('logoutform').submit()">
Logout
</a>
</li>
<form id="logoutform" method="POST" action="{% url 'account_logout' %}">
{% csrf_token %}
<input type="hidden">
</form>
You don't need a form. Simply replace the form with this:
Logout

How do I add a dynamic base template in django?

Suppose I have a base.html template. In the base.html template contains the menu bar, the fixed footer and the content block.
Exemple:
base.html
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<a class="navbar-brand mr-0 mr-md-2" href="/">
<img src="{{ url of an image added in the database that can be changed by the user }}" height="60" class="d-inline-block" alt="site">Site</a>
<button class="btn btn-link bd-search-docs-toggle d-md-none p-0 ml-3" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="#">Diário Oficial do PL</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Site Oficial do PL</a>
</li>
<li>
<a class="nav-link" href="#">Links Úteis</a>
</li>
</ul>
</div>
<div class="container" style="min-height: calc(100vh - 230px);">
{% block content %}
<!-- Blocl content -->
{% endblock %}
</div>
{% block footer %}
{% endblock %}
home.html
{% extends 'base/base.html' %}
{% load static %}
{% block conteudo %}
<p>Content bla bla bla bla bla </p>
{% endblock %}
models.py
class Orgao(models.Model):
name = models.CharField(max_length=80)
logo = models.ImageField()
How would a view that would take this image in the database and show in the base.html that is extended to all the pages of the system?
You don't have to use get_context_data in every view.
There is such thing as a context processor in django, it's made specifically to deliver context to every page of the web app.
So, in your case that would be:
# context_proccesors.py
from .models import Orgao
def orgao_logo(request):
orgao = Orgao.objects.filter(name='somename') # or whatever object you need
return {'logo':orgao.logo}
Then you need to add this context proccessor to your settings.py:
#settings.py
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [TEMPLATES_DIR],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
....
'context_processors.orgao_logo',
],
},
},
]
And finaly you can use it in your templates via the context keyword:
<img src="{{logo.url}}">
You could include the image url in the context you're returning for each view. For exemple you could use the short function render
You could also use a simple tag to return the url directly in the template

Using Django-postman tags in other html pages

SO far I've installed django-postman and it works so fine and successfully updated the default template just fine but now i want to use the django-postman tags in someother pages such as the navbar ... but i can't get it to work
here is a look at my
<li class="dropdown messages-menu">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-envelope-o"></i>
<span class="label label-success">4</span>
</a>
<ul class="dropdown-menu">
<li class="header">You have 4 messages</li>
<li>
<!-- inner menu: contains the actual data -->
<ul class="menu">
<li><!-- start message -->
<a href="#">
<div class="pull-left">
<img src="{{ user.user.photo.url }}" class="img-circle" alt="User photo">
</div>
{% block pm_sender_cell %} <h4 class="mailbox-name">{{ message.obfuscated_sender|or_me:user }}{% if message.count %} ({{ message.count }}){% endif %}</h4>{% endblock %}
<small><i class="fa fa-clock-o"></i> 5 min</small>
<p>Message Excerpt</p>
</a>
</li><!-- end message -->
...
</ul>
</li>
<li class="footer">See All Messages</li>
</ul>
</li>
my question is how can i make django-postman tags work on all my pages not only in /messages/inbox