I have 4 nav-items being generating dynamically based on the Django Model entries.
My template code is as below:
{% for stockbroker in stockbrokers %}
<li class="nav-item">
<a class="nav-link" href="{% url 'broker:display_stocks' stockbroker.id %}" id="nav">{{ stockbroker.broker_name }}
</a>
</li>
{% endfor %}
I want to highlight the currently active nav based on the id I am passing in the url section of the a tag href. Is it possible to achieve this?
I am generating these nav links in the base.html using context_processors.py
from .models import StockBroker
def stockbrokers(request):
return {'stockbrokers': StockBroker.objects.all()}
An if condition should work for this:
{% for stockbroker in stockbrokers %}
<li class="nav-item">
<a class="nav-link {% if stockbroker.id == current_id %}active{% endif %}" href="{% url 'broker:display_stocks' stockbroker.id %}" id="nav">{{ stockbroker.broker_name }}
</a>
</li>
{% endfor %}
Note: current_id (or variable name of your preference) should be passed in the context.
The context is the dictionary that is passed while rendering the template, example:
def my_view(request):
# View Code
return render(request, 'template_name.html', {'current_id': current_id})
Related
I am trying to make a codeforces crawler and I am just adding user authentication in the somehow failed to implement. Reverse not match and crawler is not a registered namespace is the error I'm getting. I don't know what files exactly are needed to put here so please ask me I will post them if you need it. I'm just a beginner and I need help.
crawler/urls.py
app_name = 'crawler'
urlpatterns = [
path('',views.index,name='index'),
path('formpage/',views.search_form_view , name='searchform'),
path('formpage/<str:handle>',views.person, name= 'person'),
path('user_login/',views.user_login,name ="user_login"),
path('logout/',views.user_logout,name="logout"),
]
base.html
<body>
<nav class="navbar navbar-expand-sm bg-dark navbar-dark">
<!-- Brand -->
<a class="navbar-brand" href="{% url 'crawler:index'%}">Crawler</a>
<!-- Links -->
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="{% url 'crawler:searchform'%}">Search</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Link 2</a>
</li>
{% if user.is_authenticated %}
<li class="nav-item">
<a class="nav-link" href="{%url 'crawler : logout'%}">Log Out</a>
</li>
{% else %}
<li class="nav-item">
<a class="nav-link" href="{%url 'crawler :user_login'%}">Login</a>
{% endif %}
</li>
</li>
</ul>
</nav>
<br>
{% block body_block %}
{% endblock %}
</body>
views.py
#login_required
def user_logout(request):
logout(request)
return HttpResponse(reverse('index'))
webcrawler/urls.py
app_name = 'crawler'
urlpatterns = [
path('admin/', admin.site.urls),
path('',include('crawler.urls',namespace= "crawler")),
]
A two-part answer here.
No reverse match at /
The point is that, in both your main and app urls.py, you registered both URLs to be '', which means that there will be a match at (empty string) but won't be one at '/'. To fix this, simply add '/' to the main urls.py as it's a better practice.
Crawler is not a registered namespace
As you call an URL, it should be {% url 'crawler:index' %} or {% url 'crawler:searchform' %} or something because crawler is the main namespace but there are multiple URLs under it so you need to pass an additional parameter after your crawler namespace.
I have a load of URLs I want to declare as constants so I can use them in for and if statements in a template. At the moment I do this manually e.g.:
{% url 'inbox' as inbox %}
{% url 'sent' as sent %}
{% url 'drafts_tasks' as drafts_tasks %}
However this feels kinda clunky and when the urls increase in numbers it is a load of extra code repeated on every template.
Is there a better way I can loop through urls and declare them?
Here's an example of how I want to use them:
{% url 'XXX' as XXX %}
{% for ....
<li class="nav-item {% if request.path == XXX %}active{% endif %}">
<a class="nav-link" href="{{ XXX.url }}">{{ XXX.name }}
</a>
</li>
endfor %}
The easiest option would be to pass the urls as a list.
class URLView(TemplateView):
template_name = 'urls.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['urls'] = get_my_list_of_urls()
return context
As for the repeated code you could make use of the include template tag.
Create a file with the repeating template fragment templates/includes/url_link_list.html:
<li class="nav-item {% if request.path == xxx %}active{% endif %}">
<a class="nav-link" href="{{ xxx.url }}">{{ xxx.name }}</a>
</li>
Then in your urls.html file that was defined in your view you will include that fragment:
<ul>
{% for url in urls %}
{% with url as xxx %}
{% include 'includes/url_link_list.html' %}
{% endwith %}
{% endfor %}
</ul>
I have a class based view that I am using to display a queryset in a table. I am also using a couple formsets to filter this queryset. I am using the get_queryset() method provided as part of the generic.ListView class to filter the diplayed results. Here is basically what my class looks like:
from django.views import generic
class UnifiedSingleSearch(generic.ListView):
template_name = 'app/foo.html'
model = MyModel
paginate_by = 30
def get_queryset(self):
if self.request.POST: # If we got here because of a search submission, filter
return MyModel.objects.filter('Some stuff base on the POST data')
return MyModel.objects.all() # Otherwise, just show everything
Because I am using a formset to submit multiple search criteria, I have to use a POST request. Upon initial submission of the form, the page reloads with a correctly filtered querset. However when I try to use my pagination controls, the POST request is thrown away and the page acts as if I am going to page#2 of MyModel.objects.all() instead of my filtered down subset.
How can I retain my filtered queryset when using pagination controls?
Here is the HTML for the pagination controls:
{% if is_paginated %}
<nav aria-label="Pagination nav">
<ul class="pagination">
{# Back a page #}
{% if page_obj.has_previous %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.previous_page_number }}">❮</a>
</li>
{% else %}
<li class="page-item disabled">
<span class="page-link">❮</span>
</li>
{% endif %}
{# Page numbers #}
{% for i in paginator.page_range %}
{% if page_obj.number == i %}
<li class="page-item active">
<span class="page-link">{{ i }}
<span class="sr-only">(current)</span>
</span>
</li>
{% else %}
<li class="page-item">
<a class="page-link" href="?page={{ i }}">{{ i }}</a>
</li>
{% endif %}
{% endfor %}
{# Next page #}
{% if page_obj.has_next %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.next_page_number }}">❯</a>
</li>
{% else %}
<li class="page-item disabled">
<span class="page-link">❯</span>
</li>
{% endif %}
</ul>
</nav>
{% endif %}
{% else %}
<p>No MyModel objects found</p>
{% endif %}
Switching to a GET request was the answer. Pagination controls also had to be edited a bit to retain the passed querystring. They should all include {{ request.GET.urlencode }} and then you tack on the page logic to the end like usual. Ends up looking something like this:
<li class="page-item">
<a class="page-link" href="?{{ request.GET.urlencode }}&page={{ page_obj.next_page_number }}">❯</a>
</li>
I have a template that looks like this in my html. It uses the bootstrap classes.
<-- navbar-template.html>
<div class="collapse navbar-collapse" id="myNavbar">
<ul class="nav navbar-nav">
<li>Home</li>
<li class='active'>Members</li>
<li>Research</li>
<li>Publications</li>
<li>Links</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li><span class="glyphicon glyphicon-log-in"></span> Login</li>
</ul>
</div>
I like the active class but I need the to change which list object it is based on which page from the navbar django has loaded.
I think you'd like to do something like this in the home.html file
<-- HOME -->
{% include "navbar_template.html" with page="home"} %}
###Do something with {{page}} variable in order to set the home list tag to active.
Do I have to write a crazy amount of if else statements or is there an easier way. Perhaps something with the views.py in django
You can do it like this (example solution I use on my page):
<ul class="sidebar-nav--primary">
{% url 'main:home' as home %}
{% url 'main:work' as work %}
{% url 'main:personal' as personal %}
<li><a href="{{ home }}" {% if request.path == home %}class="active"{% endif %}>Home</a></li>
<li><a href="{{ work }}" {% if request.path == work %}class="active"{% endif %}>Work</a></li>
<li><a href="{{ personal }}" {% if request.path == personal %}class="active"{% endif %}>Personal</a></li>
</ul>
A cleaner method would be creating a custom template tag. Something like is_active:
# Inside custom tag - is_active.py
from django.template import Library
from django.core.urlresolvers import reverse
register = Library()
#register.simple_tag
def is_active(request, url):
# Main idea is to check if the url and the current path is a match
if request.path in reverse(url):
return "active"
return ""
And use it in your templates like this:
# template.html
{% load is_active %}
<li>Home</li>
I'm building a simple blog app using Django.
This app has a main template blog.html which is shared between the following views:
blog (url: /blog/[page number])
Main page of the blog, displays the last articles
search (url: /search/<query>/[page number])
Will display the articles who match the query
category (url: /category/<category name>/[page number])
Will display the articles from the given category
Each a this views provides the template blog.html with an object page obtained using the function Paginator each time with a different objects list (depending on the view).
Here is my problem:
The template blog.html contains a pager
<ul class="pager">
{% if page.has_previous %}
<li class="previous">
<a href="{{ url_previous_page }}" class="btn btn-primary" >← Older</a>
</li>
{% endif %}
{% if page.has_next %}
<li class="next">
<a href="{{ url_next_page }}" class="btn btn-primary" >Newer →</a>
</li>
{% endif %}
</ul>
How can I define in an elegant way the values of url_next_page and url_previous_page in all the views?
You shouldn't really need to supply the links for the next and previous buttons like that. I would suggest changing your pagination code to be something like this:
<div class="pagination-wrap">
<span class="pagination-links">
{% if page_obj.has_previous %}
{% endif %}
<span class="current">
{{ page_obj.number }} of {{ page_obj.paginator.num_pages }}
</span>
{% if page_obj.has_next %}
{% endif %}
</span>
<div>{{ page_obj.start_index }} to {{ page_obj.end_index }} of {{ page_obj.paginator.count }}</div>
</div>
In your views, all you need to specify is the number of objects to paginate by with paginate_by = 15.
If you really want to, you could create a mixin for your list views to use which has a method that could return the url you want.