How do I add a dynamic base template in django? - 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

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 %}

Py 3.6 // Django 2.1.4 : Accessing User Profile mysteriously changes the status of user.is_authenticated to True

I have been having this problem for 2 weeks now I can't seem to solve it.
I have a social website where user's can upload their resumes for recruiters to see.
And when I access some user's profile, the Navbar acts as if I am logged in, which I am not.
I tried fixing this issue by using get_queryset() ,it worked but I couldn't manage to display user's profile data.
so I stuck with get().
Here's a visual explanation:
As you can see the navbar says Home/Login/Signin
Now if I access John Doe's Profile, the navbar will switch to Home/Profile/Logout:
Here's my code;
views.py:
class HomeProfile(ListView):
"Di splays all active users in db"
template_name = 'profile/home_profile.html'
queryset = MyModel.objects.filter(is_active=True)
class Get_Profile(DetailView):
"fetches user's profile"
def get(self, request, pk):
user = MyModel.objects.get(pk=pk)
return render(request, 'profile/profile.html', {'user':user})
urls.py
urlpatterns = [
path('homepage/profiles/', user_view.HomeProfile.as_view(), name='homepage'),
path('homepage/profile/<int:pk>/', user_view.Get_Profile.as_view(), name='user-profile'),
]
base_test.html
<nav class="navbar navbar-expand-sm navbar-dark bg-dark sticky-top">
<a class="navbar-brand" href="{% url 'home' %}">Navbar</a>
<button class="navbar-toggler d-lg-none" type="button" data-toggle="collapse" data-target="#collapsibleNavId" aria-controls="collapsibleNavId"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="collapsibleNavId">
<ul class="navbar-nav ml-auto mt-2 mt-lg-0">
<li class="nav-item active">
<a class="nav-link" href="{% url 'homepage' %}">Home<span class="sr-only">(current)</span></a>
</li>
{% if not user.is_authenticated %}
<li class="nav-item">
<a class="nav-link" href="{% url 'login' %}">Log In</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'signup' %}">Sign Up</a>
</li>
{% else %}
<li class="nav-item">
<a class="nav-link" href="#">Profile</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'logout' %}">Log Out</a>
</li>
{% endif %}
</ul>
</div>
</nav>
home_profile.html
<!-- this is the home template that displays all active users -->
{% extends 'base_test.html' %}
{% block title %} My Site | Profiles {% endblock title %}
{% block content %}
<div class="card-columns text-center padding">
{% for user in mymodel_list %}
<div class="card">
<img class="rounded-circle" src="{{user.profile.image.url}}" width=150 height=150>
<div class="card-body">
<h5 class="card-title">Full name : {{user.get_full_name}}</h5>
<p class="crad-text">Occupation/job : {{user.profile.occupation}}</p>
<a type="button" href="{% url 'user-profile' user.pk %}" style="color:whitesmoke;" class="btn btn-primary btn-sm">Profile</a>
</div>
</div>
{% endfor %}
</div>
{% endblock content %}
{% block footer %}
{% endblock footer %}
profile.html
<!-- user profile template -->
{% extends 'base_test.html' %}
{% load custom_tags %}
{% block title %} My Site | {{user.get_full_name}} {% endblock title %}
{% block content %}
<div class="container">
<div class="row">
<div class="col-lg-8 order-lg-2 padding">
<div class="tab-content">
<div class="tab-pane active" id="profile">
<div class="row">
<div class="col-lg-12">
<h6><strong>About</strong></h6>
<p>
{{user.profile.bio}}
</p>
<hr>
</div>
<div class="col-lg-12">
<h6><strong>Skills</strong></h6>
{% for skill in user.profile.skills|split:',' %}
<span class="badge badge-primary">{{skill}}</span>
{% endfor %}
<hr>
<h6><strong>Hobbies</strong></h6>
<p>
{% for hobbie in user.profile.hobbies|split:',' %}
<span class="badge badge-success">{{hobbie}}</span>
{% endfor %}
</p>
<hr>
</div>
<!-- removes the social part -->
</div>
</div>
</div>
</div>
<div class="col-lg-4 order-lg-1 padding">
<h1 class="mb-3 text-center">{{user.get_full_name}}</h1>
<hr>
<img src="{{user.profile.image.url}}" class="mx-auto img-fluid rounded-circle d-block" alt="avatar" width=150><br>
<div class="text-center">
<h4>{{user.profile.school}}</h4>
<p><strong>Hometown :</strong> {{ user.profile.hometown}}</p>
<p><strong>Current City:</strong> {{user.profile.location}}<p>
<p><strong>Occupation/Job:</strong> {{user.profile.occupation}}<p><br>
<hr>
<button type="button" class="btn btn-outline-success btn-md">View CV</button>
</div>
</div>
</div>
</div>
{% endblock content %}
{% block footer %}
{% endblock footer %}
I don't know What is causing this strange behaviour!!
Actually, you are mixing up with request.user and your user object for resume. You should change the context variable name from user to something else. for example:
class Get_Profile(DetailView):
"fetches user's profile"
def get(self, request, pk):
user = MyModel.objects.get(pk=pk)
return render(request, 'profile/profile.html', {'profile':user}) # <-- Here
You've used the same variable name, user, for the user whose profile you are viewing as for the one who is actually using the site. You need to pick another name.
(Also, unrelated, but you don't need to - and shouldn't - define the get method in your detail view.)

Display Image in Django

I've been unable to make this work although I realise there are similar questions. Hoping someone can point me in the right direction.
I have a django app which allows uploads of images with it. Right now my model looks like this.
The image is not displaying for some reason when it is called from the code. The reasons I can imagine are in the view.py file, or how I am calling it in the template file.
Appreciate your help in advance,
MODELS
class Category(models.Model):
name = models.CharField(max_length=128, unique=True)
image = models.ImageField(blank=True, null=True, upload_to="locations/%Y/%m/%D")
views = models.IntegerField(default=0)
likes = models.IntegerField(default=0)
slug = models.SlugField(unique=True)
def save(self, *args, **kwargs):
self.slug = slugify(self.name)
super(Category, self).save(*args, **kwargs)
class Meta:
verbose_name_plural = 'categories'
def __str__(self):
return self.name
VIEWS
def index(request):
# Query the databse for a list of ALL categories currently stored.
# Order the categories by no likes in descending order .
# Retrieve the top 5 only - or all if less than 5.
# Place the list in context_dict dictionary
# that will be passed to the template engine.
category_list = Category.objects.order_by('-likes')[:5]
page_list = Page.objects.order_by('-views')[:5]
context_dict = {'categories': category_list, 'pages': page_list}
# Render the response and send it back!
return render(request, 'Spaces/index.html', context_dict)
def show_category(request, category_name_slug):
# Create a context dictionary which we can pass
# to the template rendering engine.
context_dict = {}
try:
# Can we find a category name slug with the given name?
# If we can't, the .get() method raises a DoesNotExist exception.
# So the .get() method returns one model instance or raises an exception.
category = Category.objects.get(slug=category_name_slug)
# Retrieve all of the associated pages.
# Note that filter() returns a list of page objects or an empty list
pages = Page.objects.filter(category=category)
# Adds our results list to the template context under name pages.
context_dict['pages'] = pages
# We also add the category object from
# the database to the context dictionary.
# We'll use this in the template to verify that the category exists.
context_dict['category'] = category
# We get here if we didn't find the specified category.
# Don't do anything -
# the template will display the "no category" message for us.
except Category.DoesNotExist:
context_dict['category'] = None
context_dict['pages'] = None
# Go render the response and return it to the client.
return render(request, 'Spaces/category.html', context_dict)
TEMPLATES
{% load staticfiles %}
{% load i18n %}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Side Spacer</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
<script src="https://use.fontawesome.com/releases/v5.0.8/js/all.js"></script>
<link href="style.css" rel="stylesheet">
</head>
<body>
<!-- Navigation -->
<nav class="navbar navbar-expand-md navbar-light bg-light sticky-top">
<div class="container-fluid">
<a class="navbar-brand" href="#"><img src="#"></a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarResponsive">
<ul class="navbar-nav ml-auto">
<li class="nav-item active"><a class="nav-link" href="#">Home</a></li>
<li class="nav-item"><a class="nav-link" href="#">Spaces</a></li>
<li class="nav-item"><a class="nav-link" href="/Spaces/about/">How it works</a></li>
<li class="nav-item"><a class="nav-link" href="#">Pricing</a></li>
{% if user.is_authenticated %}
<li class="nav-item"><a class="nav-link" href="{% url 'logout' %}">Log out {{user.username}}</a></li>
{% else %}
<li class="nav-item"><a class="nav-link" href="{% url 'signup' %}">Sign Up</a></li>
<li class="nav-item"><a class="nav-link" href="{% url 'login' %}">Login</a></li>
{% endif %}
</ul>
</div>
</div>
</nav>
<!--- Image Slider -->
<div id="slides" class="carousel slide" data-ride="carousel">
<ul class="carousel-indicators">
<li data-target="#slides" data-slide-to="0"class="active"></li>
</ul>
<div class="carousel-inner">
<div class="carousel-item active">
<div class="carousel-caption">
<h3 class="display-2">Need a workspace on the go?</h3>
<h3>Great locations and flexible pricing!</h3>
<button type="button" class="btn btn-outline-light btn-lg" href="{% url 'signup' %}">Join Now!</button>
</div>
</div>
</div>
</div>
<!--- Jumbotron -->
<hr class="my-4">
<div class="container-fluid">
<div class="row jumbotron">
<div class="col-xs-12 col-sm-12 col-md-9 col-lg-9 col-xl-10">
<p class="lead">For mobile professionals, startups, and business that need the extra deskpace!<br> Productive workspaces are available to help you get things done!<br> Our plans start at $99/month! </p>
</div>
<div class="col-xs-12 col-sm-12 col-md-3 col-lg-3 col-xl-2">
<button type="button" class="btn btn-outline-secondary btn-lg">Our Services</button>
</div>
</div>
</div>
<div class="container">
<!-- Example row of columns -->
<div class ="row">
<div class ="col">
<h2>Most Viewed Spaces</h2>
{% if categories %}
<ul>
{% for category in categories %}
<li>
{% if item != None %}
<img src="{% get_media_prefix %}{{ category.image }}" width="500px" />
{% endif %}
{{ category.name }}
</li>
{% endfor %}
</ul>
{% else %}
<strong>There are no Spaces present.</strong>
{% endif %}
</div>
<div class ="col">
<h2>Most Viewed Events</h2>
<p>
{% if pages %}
<ul>
{% for page in pages %}
<li>{{ page.title }}</span></li>
{% endfor %}
</ul>
{% else %}
<strong>There are no Events present.</strong>
{% endif %}
</p>
</div>
<div>
{% if user.is_authenticated %}
<div>
<p><a class="btn btn-success" href="/Spaces/add_category/" role="button">Add New Space »</a></p>
<p><a class="btn btn-success" href="/Spaces/add_page/" role="button">Create New Event »</a></p>
</div>
{% endif %}
</div> <!-- /container -->
<hr>
<div class="container-fluid padding">
<div class="row text-center">
<div class="col-md-4">
<hr class="light">
<img src="#">
<hr class="light">
<p>555-555-55555</p>
<p>email#someonesmail.com</p>
<p>100 Street name</p>
<p>City, State, 0000</p>
</div>
<div class="col-md-4">
<hr class="light">
<h5>Our hours</h5>
<hr class="light">
<p>Monday: 9AM - 5PM</p>
<p>Saturday: 10AM - 4PM</p>
<p>Sunday: Closed</p>
</div>
<div class="col-md-4">
<hr class="light">
<h5>Service Area</h5>
<hr class="light">
<p>City, State, 0000</p>
<p>City, State, 0000</p>
<p>City, State, 0000</p>
</div>
<div class="col-12">
<hr class="light">
<h5>© nameofthebusiness </h5>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script>window.jQuery || document.write('<script src="../../assets/js/vendor/jquery-slim.min.js"><\/script>')</script>
<script src="../../assets/js/vendor/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
</body>
</html>
You have to add get_media_prefix before the image. I use {{ category.image.url }} to serve media from AWS S3, but I think here you would just use {{ category.image }}. Play with it a little bit and see.
<img src="{% get_media_prefix %}{{ category.image }}" width="500px" />
You should give proper path for the image. for me below code works properly.
in settings:
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
to display image
<img src="/media/{{category.image}}" width="500px" />
Found the problem.
{% if item != None %}
<img src="{% get_media_prefix %}{{ category.image }}" width="500px" />
{% endif %}
Changed too
{% if category.image %}
<img src="{{ category.image.url }}" />
{% endif %}
Problem solved

Make clicked tab active in Bootstrap

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>