Highlighting link of currently opened category tab in css - python

I am trying to highlight a link of a currently opened category tab, here is what i have already done:
globs.py
def globs(request):
cats = Category.objects.all()
return {'cats': cats}
views.py
def news_by_category(request, slug):
c = Category.objects.get(slug=slug)
news = News.objects.filter(category=c, status='p').order_by('-id')
#news = c.news_set.all().order_by('-id')
return object_list(
request,
news,
paginate_by = 5,
extra_context = {'c':c},
template_name = 'news_by_category.html')
base.html #bodyclass
<body class="{% block bodyclass %}{% endblock %}">
news_by_category.html
{% block bodyclass %}{{c|cut:" "}}{% endblock %}
base.html
<li><h4>Categories:</h4></li>
{% for i in cats %}
<li class="{{i.name|safe|cut:" "}}_li">
{{ i.name }}
</li> {% endfor %}
What i need to do now is to create style for every category, in category list, I could achieve this easily by styling inside a html file, but I'm not sure wether that would be proper (Would it?). I came up with some css styling,
{% for i in cats %}
body.{{ i|safe|cut:" "}} li.{{i|safe|cut:" "}}_li {
color: red;
}
but as I can't use django template tags inside my .css file, this wont work.
My questions:
1) How could i make this css file work for me. Any chance for a little step by step?
2) If I failed step1, how improper would it be to style those few li elements inside html file?
EDIT: /trying another way
I tried using:
base.html
{% for i in cats %}
<li class="{% ifequal 'request.get_full_path' '/k/{{ i.slug }}/' %}active{% endifequal %}">
{{ i.name }}
</li> {% endfor %}
.css
.active {{color:red;}
When i compared {{ request.get_full_path }} and /k/{{i.slug}}/ both returned same thing... but if its inside ifequal it doesnt seem to work.

You can create a simple class named "active" or something along those lines and add it to the current tab. Then, in your CSS you apply the active styles to that class. So you just append the active class and it'll automatically take the active style.

If you have a url:
{% url app:home i.slug as home %}
<li {% ifequal request.get_full_path home %}class="active"{% endifequal %}>

Related

link in html do not function

python 2.7 DJANGO 1.11.14 win7
when I click the link in FWinstance_list_applied_user.html it was supposed to jump to FW_detail.html but nothing happened
url.py
urlpatterns += [
url(r'^myFWs/', views.LoanedFWsByUserListView.as_view(), name='my-applied'),
url(r'^myFWs/(?P<pk>[0-9]+)$', views.FWDetailView.as_view(), name='FW-detail'),
views.py:
class FWDetailView(LoginRequiredMixin,generic.ListView):
model = FW
template_name = 'FW_detail.html'
models.py
class FW(models.Model):
ODM_name = models.CharField(max_length=20)
project_name = models.CharField(max_length=20)
FW_detail.html
{% block content %}
<h1>FW request information: {{ FW.ODM_name}};{{ FW.project_name}}</h1>
<p><strong>please download using this link:</strong> {{ FW.download }}</p>
{% endblock %}
FWinstance_list_applied_user.html
{% block content %}
<h1>Applied FWs</h1>
{% if FW_list %}
<ul>
{% for FWinst in FW_list %}
{% if FWinst.is_approved %}
<li class="{% if FWinst.is_approved %}text-danger{% endif %}">-->
{{FWinst.ODM_name}} ({{ FWinst.project_name }})
</li>
{% endif %}
{% endfor %}
</ul>
{% else %}
<p>Nothing.</p>
{% endif %}
{% endblock %}
the image of FWinstance_list_applied_user.html, when I click the link CSR, nothing happened
You haven't terminated your "my-applied" URL pattern, so it matches everything beginning with "myFWs/" - including things that that would match the detail URL. Make sure you always use a terminating $ with regex URLs.
url(r'^myFWs/$', views.LoanedFWsByUserListView.as_view(), name='my-applied'),
You are seeing this behavior because your first URL pattern is not terminated. The regular expression r'^myFWs/' also matches the URL path myFWs/123, so your FW-detail URL is never matched. You can fix that by simply appending a $ to your URL pattern.
urlpatterns += [
url(r'^myFWs/$', views.LoanedFWsByUserListView.as_view(), name='my-applied'),
# ^ this was missing

Statik: Implement navigation from data/views

I have a website build via Statik (a static web site generator, build with python).
Now I'd like to build a navigation out from my existing data or views, via a property like e.g. show_in_navigation = Boolean.
I thought about writing a custom template tag to get a list of all instances with show_in_navigation = True - but I don't know where to start or what would be the best approach in the first place;-)
My goal is a Twitter Bootstrap navbar-nav component filled with my show_in_navigation entries (with a bonus for highlighting the current page).
Any hints or tips?
My current implementation defines a navigation_bar variable in the main configuration:
# config.yml
context:
static:
navigation_bar: [['home', 'Home'], ['about', 'About'], ['contact', 'Contact']]
# templates/includes/navigation.html
<ul>
{% for pk, title in navigation_bar %}
<li {% if pk == active_page %} class="active"{% endif %}>
{{ title }}
</li>
{% endfor %}
</ul>
# templates/about.html
{% extends "base.html" %}
{% set active_page = "about" %}
... but that seems to be very verbose and not dry (e.g. repeating site titles, setting the active page)...

Django How can I cache properly to reuse data?(with using django-mptt package and redis module)

I am making kind of dynamic menu. when you click menu on the top, it show sub menu on the left side. I searched with keyword 'dynamic menu' from stackoverflow and google. I got idea to build that kind of menu. I made it like below.
1) render data(menu list) in context to template by custom context processor.
2) using custom template tag which is provided by django-mptt package.
3) show top menu in base template.
4) move to another template to show sub menu according to what top menu you click
I made custom context_processor to use menu in context in every template.
context_processor.py
from manager.models import Menu
def menu(request):
menu_list = list(Menu.objects.all())
return {'menu':menu_list}
template.py(example)
{% load mptt_tags %}
<nav id="{{ menu_id }}" class="tree-menu">
<ul>
{% recursetree menu %}
<li class="menu
{% if node.is_root_node %}root{% endif %}
{% if node.is_child_node %}child{% endif %}
{% if node.is_leaf_node %}leaf{% endif %}
{% if current_menu in node.get_descendants %}open{% else %}closed{% endif %}
">
{{ node.menu_name }}
{% if not node.is_leaf_node %}
<ul class="children">
{{ children }}
</ul>
{% endif %}
{% if node.items and node.items.exists %}
<ul class="items">
{% for item in node.items.all %}
{% if item_template %}
{% include item_template %}
{% else %}
{% include "menu/tree-item.html" %}
{% endif %}
{% endfor %}
</ul>
{% endif %}
</li>
{% endrecursetree %}
</ul>
</nav>
mptt_tags.py
#register.tag
def recursetree(parser, token):
"""
Iterates over the nodes in the tree, and renders the contained block for each node.
This tag will recursively render children into the template variable {{ children }}.
Only one database query is required (children are cached for the whole tree)
Usage:
<ul>
{% recursetree nodes %}
<li>
{{ node.name }}
{% if not node.is_leaf_node %}
<ul>
{{ children }}
</ul>
{% endif %}
</li>
{% endrecursetree %}
</ul>
"""
bits = token.contents.split()
if len(bits) != 2:
raise template.TemplateSyntaxError(_('%s tag requires a queryset') % bits[0])
queryset_var = template.Variable(bits[1])
template_nodes = parser.parse(('endrecursetree',))
parser.delete_first_token()
return RecurseTreeNode(template_nodes, queryset_var)
My Question
If you see django manual about QuerySet, it says that "Each QuerySet contains a cache to minimize database access". It is obvious that, if you query same data in certain rule, it doesn't seem hit database again but return result from cache. Then I am querying Menu.objects.all() in custom context processor. This result(menu_list = Menu.objects.all()) will be in context every time, you can use menu data on every template repeately. So does it reuse the result from cache without hitting database again?
If menu_list = Menu.objects.all() in custom context processor hit database every time whenever template load this menu list, Does it work in this way to reuse menu data from cache without hitting database everytime?
context_processors.py
from manager.models import Menu
from django.core.cache import cache
def menu(request):
menu_list = cache.get_or_set('menu_list', list(Menu.objects.all()))
return {'menu':menu_list, 'redis':"Food"}
Lastly, I don't know if there are many people using django-mptt package. I guess just a few people have experience using it in person. It says "Only one database query is required (children are cached for the whole tree)" so does it mean if I use django-mptt package and get menu from it on template, it automatically cache its data?
Well, I am not clear about django cache system.
It would be really appreciate if you can give me answer and insight for my questions. Thanks for reading!

Changing the active class of a link with the twitter bootstrap css in python/flask

I got the following html snippet from my page template.html.
<ul class='nav'>
<li class="active"><a href='/'>Home</a></li>
<li><a href='/lorem'>Lorem</a></li>
{% if session['logged_in'] %}
<li>Account</li>
<li>Projects
<li>Logout</li>
{% endif %}
{% if not session['logged_in'] %}
<li>Login</li>
<li>Register</li>
{% endif %}
</ul>
As you can see on line 2, there's the class active. This highlights the active tab with the twitter bootstrap css file. Now, this will work fine if I would visit www.page.com/ but not when I would visit www.page.com/login for example. It would still highlight the home link as the active tab.
Of course, I could easily do this with Javascript/jQuery but I'd rather not use that in this situation.
There's already a working solution for ruby on rails but I don't know how to convert that into python/jinja (I'm rather new to jinja/flask, never worked with ruby at all)
Have you looked at this ? https://jinja.palletsprojects.com/en/3.0.x/tricks/#highlighting-active-menu-items
Highlighting Active Menu Items
Often you want to have a navigation bar with an active navigation item. This is really simple to achieve. Because assignments outside of blocks in child templates are global and executed before the layout template is evaluated it’s possible to define the active menu item in the child template:
{% extends "layout.html" %}
{% set active_page = "index" %}
The layout template can then access active_page. Additionally it makes sense to define a default for that variable:
{% set navigation_bar = [
('/', 'index', 'Index'),
('/downloads/', 'downloads', 'Downloads'),
('/about/', 'about', 'About')
] -%}
{% set active_page = active_page|default('index') -%}
...
<ul id="navigation">
{% for href, id, caption in navigation_bar %}
<li{% if id == active_page %} class="active"{% endif
%}>{{ caption|e }}
</li>
{% endfor %}
</ul>
Here is another simpler way if you have menus distributed all over the page. This way uses inline if statements to print out the class active.
<ul>
<li class="{{ 'active' if active_page == 'menu1' else '' }}">
Link 1
</li>
<li class="{{ 'active' if active_page == 'menu2' else '' }}">
Link 2
</li>
</ul>
Class active is for highlighting
You still need to set the variable on every page to mark them
{% extends "master.html" %}
{% set active_page = "menu1" %}
or
{% set active_page = "menu2" %}
For jinja/flask/bootstrap users:
If you define your nav like they did in the blog example http://getbootstrap.com/examples/blog/
simply assign ids to your links that match your url_for arguments and you just need to modify the layout-template, the rest just works #magic.
<nav class="blog-nav">
<a id="allposts" class="blog-nav-item" href="{{ url_for('allposts')}}">All Posts</a>
<a id="index" class="blog-nav-item" href="{{ url_for('index')}}">Index</a>
<a id="favorites" class="blog-nav-item" href="{{ url_for('favorites')}}">Favorites</a>
</nav>
At the bottom of your base/layout template just add this
<script>
$(document).ready(function () {
$("#{{request.endpoint}}").addClass("active"); })
</script>
and the right elements will be set active.
EDIT:
If you have a layout with elements in a list, like this:
<nav class="blog-nav">
<ul class="nav navbar-nav">
<li>
<a id="allposts" class="blog-nav-item" href="{{ url_for('allposts')}}">All Posts</a>
</li>
<li>
<a id="index" class="blog-nav-item" href="{{ url_for('index')}}">Index</a>
</li>
<li>
<a id="favorites" class="blog-nav-item" href="{{ url_for('favorites')}}">Favorites</a>
</li>
</ul>
</nav>
use the parent() function to get the li element instead of the link.
<script>
$(document).ready(function () {
$("#{{request.endpoint}}").parent().addClass("active"); })
</script>
we can make class active by using jinja if statements
<ul class="nav navbar-nav">
<li class="{% if request.endpoint=='home' %}active{%endif %}">home</li>
<li class="{% if request.endpoint=='add_client' %}active{%endif %}">Add Report</li>
</li>
</ul>
I liked #philmaweb's approach, but there's really no reason to require duplicating the endpoint in the id of each element.
base.js:
$(document).ready(function () {
var scriptElement = $('#baseScript')[0];
var path = scriptElement.getAttribute('data-path');
$('a[href="'+path+'"]').addClass("active");
});
base.html
<script id="baseScript" src="{{ url_for('static', filename='js/base.js') }}"
data-path="{{ request.path }}"></script>
Why not just put this script inline? You could, of course, but allowing inline JS is a security nightmare. You should be using a CSP on your site (e.g. Flask-Talisman) which will not allow inline JS. With data-* attributes, it's not hard to do this in a secure way.
NB: If you have multiple links leading to the same, current page and you want only ONE of them to be marked "active"—then this approach may not work for you.
I tried different solution for this for the solution 1st by Codegeek didn't work as I have multiple Ul and li under it so I just include my navbar in template.html
{% include 'sidebar.html' %}
then in Navbar file in the li class you can set active with help of "request.endpoint" but then again it will return you entire route instead use split and take last route name and set active if same for exmaple
<li class="{% if request.endpoint.split('.')[1] == 'index' %} active {% else %} {% endif %}">
request.endpoint.split('.')[1] will return the route eg localhost/example. You will get example which you can compare and use. If you won't split and use request.endpoint than you will get 'file.example' (entire route).
Add the following CSS somewhere on your page:
a[href $= {{ page_name|default("'/'"|safe) }}]{ [INSERT YOUR ACTIVE STYLING HERE] }
Now, on each template define page_name, for example:
{% extends "template.html" %}
{% set page_name = "gallery" %}
This seems much simpler and easier to build on, than other options.
EDIT:
Almost 1 year later I'm returning to make this a much simpler fix, because setting the page name on every page is pretty inefficient.
Instead create a function like so:
#app.context_processor
def context_processor():
out = {}
out['request'] = request # Make sure you import request from flask
return out
This will allow you to pass variables implicitly to jinja, in this case we are passing the request for access to request.url_rule which contains the route the user is accessing. In the previous version, we just change {{ page_name|default("'/'"|safe) }} to "{{ request.url_rule|safe }}". Much cleaner.
I did not want to have to define the ID in the child pages, as many of the links I have do not have a specific child template.
Using the request.base_url and if it matches the _external url_for the route, then render that nav item as active.
{% set nav_items = [
("public.home", "Home"),
("public.downloads", "Downloads"),
("public.about", "About")
("account.login", "Login"),
]
-%}
...
<ul class="navbar-nav mr-auto">
{% for route, display_text in nav_items %}
<li class={% if request.base_url == url_for(route, _external=True) %}"nav-item active"{% else %}"nav-item"{% endif %}>
<a class="nav-link" href="{{ url_for(route) }}">{{ display_text }}
{% if request.base_url == url_for(route, _external=True) %}<span class="sr-only">(current)</span>{% endif %}
</a>
</li>
{% endfor %}
</ul>

webapp2, Jinja2: how to cut large html file into multiple html files

When I blog, I like to separate each blog-post into its own .html file (is that ok?)
This prevents the file getting too big, and makes it easy to go back and edit a previously written blog post if need be.
Occasionally the blog post will contain css/js/ajax/template variables.
But on my website, I like all the blog posts on one page (so I can scroll through them all, instead of going to a separate page for each post)
Here is an html file that contains two blog posts:
{% extends "base.html" %}
{% block blog_posts %}
<!-- links/targest for the side menu to jump to a post -->
<li>Post2 - April 2012</li>
<li>Post1 - Feb 2012</li>
{% endblock %}
{% block content %}
<div id="post1">
spam1 blah blah
</div>
<div id="post2">
spam2
</div>
{% endblock %}
and in base.html I have something like:
<div id="content-container">
<div id="section-navigation">
<ul>
{% block blog_posts %}
{% endblock %}
</ul>
</div>
<div id="content">
{% block content %}{% endblock %}
</div>
</div>
What is the best way for me to split these blog posts out into separate files using webapp2 and jinja2?
e.g. blog1.html might look like:
{% block blog_posts %}
<!-- links/targest for the side menu to jump to a post -->
<li>Post1 - Feb 2012</li>
{% endblock %}
{% block content %}
<div id="post1">
spam1 blah blah
</div>
{% endblock %}
(And I would want the links and the blogposts to be displayed in the right order on the website)
I could think of a way of doing it where post2 extends post1.html, post3 extends post2.html etc, but I would prefer to fan out more
"Henry and Kafura introduced Software Structure Metrics Based on Information Flow in 1981[2] which measures complexity as a function of fan in and fan out."
Thanks
#robert king, your design has data embedded directly in the template. Templates should only contain the blueprint to a view, and they should be rendered with new data generated from your main code every time. I simulate this process here (Edited to illustrate the use of a loop to extract post titles, and the display of a single post.):
import jinja2
# NOTE: in this template there is no data relating to specific posts.
# There are only references to data structures passed in from your main code
page_template = jinja2.Template('''
<!-- this is a navigation block that should probably be in base.html -->
{% block blog_posts %}
<!-- links/targets for the side menu to jump to a post -->
{% for post in posts %}
<li><a href="{{ post.url }}">{{ post.title }}
- {{ post.date }}</a></li>
{% endfor %}
{% endblock %}
<!-- this is a content block that should probably be in page.html -->
{% block content %}
<div id="post">
<h1>{{ current.title }}</h1>
<h2>{{ current.date }}</h2>
<p>{{ current.content }}</p>
</div>
{% endblock %}
''')
# NOTE your main code would create a data structure such as this
# list of dictionaries ready to pass in to your template
list_of_posts = [
{ 'url' : '#post1',
'title' : 'My first post',
'date' : 'Feb 2012',
'content' : 'My first post is about Hello World.'},
{ 'url' : '#post2',
'title' : 'My second post',
'date' : 'Apr 2012',
'content' : 'My second post is about Foo Bar.'}
]
# Pass in a full list of posts and a variable containing the last
# post in the list, assumed to be the most recent.
print page_template.render(posts = list_of_posts,
current = list_of_posts[-1])
Hope this helps.
EDIT See also my answer to a question on "Site fragments - composite views"
I just found another option in the jinja2 tutorial. I think it makes more sense for my handler to pass my template a list of filenames of blog posts, and then to include the blog posts.
include - returns the rendered contents of that file into the current namespace:
{% include 'header.html' %}
<div ...
{% include 'footer.html' %}
Included templates have access to the variables of the active context by default. For more details about context behavior of imports and includes see Import Context Behavior.
From Jinja 2.2 onwards you can mark an include with ignore missing in which case Jinja will ignore the statement if the template to be ignored does not exist. When combined with with or without context it has to be placed before the context visibility statement. Here some valid examples:
{% include "sidebar.html" ignore missing %}
{% include "sidebar.html" ignore missing with context %}
{% include "sidebar.html" ignore missing without context %}
New in version 2.2.
You can also provide a list of templates that are checked for existence before inclusion. The first template that exists will be included. If ignore missing is given, it will fall back to rendering nothing if none of the templates exist, otherwise it will raise an exception. Example:
{% include ['page_detailed.html', 'page.html'] %}
{% include ['special_sidebar.html', 'sidebar.html'] ignore missing %}
When I read the raw html file (file.read()) and passed the data to my template, it escaped all the html.
instead of {{data}} i had to use {{data|safe}} which allowed raw html.
something like:
class HomeHandler(BaseHandler):
def get(self):
file_names = sorted(os.listdir('blog_posts'))
html = [open('blog_posts/%s' % fn).read() for fn in file_names]
templates = {'html': enumerate(html)}
self.render_template('home.html', **templates)
{% block content %}
{% for num,data in html %}
<div id="post{{num}}">
{{data|safe}}
</div>
<br />
<img src="http://www.sadmuffin.net/screamcute/graphics/graphics-page-divider/page-divider-007.gif" border=0>
<br />
{% endfor %}
{% endblock %}
(make sure the directory isn't a static directory)

Categories

Resources