Pass *args in django templates - django

I did use django pagination, but there is a problem with urls, here is my urls.py:
url(r'^/blog/$', blog_view.main, name='blog'),
url(r'^/blog/page/(?P<page_id>\d{0,9})$', blog.post, name='blog_page'),
My views.py:
def post(request, page_id=None):
posts = Posts.objects.all()
pageid = page_id
return render(request, 'base.html', {'posts': posts, 'pageid': pageid,})
My base.html which use bootstrap:
{% url 'blog_page' as blog_page %} # Blog page need follow patterns
<ul>
{% for post in posts %}
<li {% if request.path == htt://myblog.com/blog/page/5 %} class="active" {% endif %}>{{ post.title }}</li> # When I put blog_page django shows error. Help me how to put something to fix this condition.
{% endfor %}
</ul>

As stated in the documenation on HttpRequest objects,
HttpRequest.path is
A string representing the full path to the requested page, not including the scheme or domain.
Example: "/music/bands/the_beatles/"
(emphasis mine).
So, in your test, leave out the scheme (which you, btw, incorrectly wrote as htt://) and domain parts:
<li {% if request.path == /blog/page/5 %} class="active" {% endif %}>{{ post.title }}</li>

Related

Django template variable not set

The title says everything. Two days ago the following code worked fine but now journeys is not set or empty or ...
def map(request, jid):
journeys = None
if request.user.is_authenticated:
journeys = Journey.objects.filter(user_id=request.user.id)
#some stuff
context = {
'jc': len(journeys), #only for testing
'journeys': journeys
}
return render(request, 'JourneyMap/map.html', context)
map.html extends base.html
Inside base.html:
<div class="dropdown-menu" aria-labelledby="dropdown05">
<p>{{ jc }}</p> <-- only for testing
{% for journey in journeys %}
{% if journey.user_id == user.user_id %}
{% if forloop.counter < 4 %}
<a class="dropdown-item"
href="{% url 'JourneyMap_journey' jid=journey.id %}">{{ journey.title }}</a>
{% endif %}
{% endif %}
{% endfor %}
</div>
Result:
It seems like journeys length is 1, so the variable is actually set.
I think that your user check fails here.
{% if journey.user_id == user.user_id %}
What is user.user_id here? Is user another variable that lives somewhere outside of the given context? Then probably it's not set.
Otherwise, if you want to check for current user's id, perhaps you should do:
{% if journey.user_id == request.user.id %}

How to dynamically call a Django templatetag from a variable

I'm trying to allow for dynamic template tags. Specifically, I have a menu setup that I'm defining in code vs templates. And I would like to render the menu label as {{ request.user }}. So how can I define that as a string in Python, and allow the template to parse and render the string as intended. And not just variables too, templatetags as well ({% provider_login_url 'google' next=next %}).
What am I missing?
Update with code:
I'm specifically designing my menus with django-navutils, but that's less important (basically the package just stores the defined data and then uses templates to render it).
from navutils import menu
top_horizontal_nav = menu.Menu('top_nav')
left_vertical_nav = menu.Menu('left_nav')
menu.register(top_horizontal_nav)
menu.register(left_vertical_nav)
sign_in = menu.AnonymousNode(
id='sign_in',
label='Sign In',
url='{% provider_login_url "google" next=next %}',
template='nav_menu/signin_node.html',
)
user = menu.AuthenticatedNode(
id='user_menu',
label='{{ request.user }}',
url='#',
template='nav_menu/username_node.html'
)
top_horizontal_nav.register(sign_in)
top_horizontal_nav.register(user)
What I would like to do, is now render these string values ('{{ request.user }}') in my templates
{% load navutils_tags %}
<li
class="{% block node_class %}nav-item menu-item{% if node.css_class %} {{ node.css_class }}{% endif %}{% if is_current %} {{ menu_config.CURRENT_MENU_ITEM_CLASS }}{% endif %}{% if has_current %} {{ menu_config.CURRENT_MENU_ITEM_PARENT_CLASS }}{% endif %}{% if viewable_children %} has-children has-dropdown{% endif %}{% endblock %}"
{% for attr, value in node.attrs.items %} {{ attr }}="{{ value }}"{% endfor %}>
<a href="{{ node.get_url }}" class="nav-link"{% for attr, value in node.link_attrs.items %} {{ attr }}="{{ value }}"{% endfor %}>{% block node_label %}{{ node.label }}{% endblock %}</a>
{% if viewable_children %}
<ul class="{% block submenu_class %}sub-menu dropdown{% endblock %}">
{% for children_node in viewable_children %}
{% render_node node=children_node current_depth=current_depth|add:'1' %}
{% endfor %}
</ul>
{% endif %}
</li>
So, for the above, where I'm rendering {{ node.label }}, how can I get the value stored in node.label to actually be parsed as a request.user? This similarly applies for the URL of value {% provider_login_url "google" next=next %}.
You can create a custom template tag and render those. Like this
from django import template
register = template.Library()
#register.simple_tag(takes_context=True)
def render_nested(context, template_text):
# create template from text
tpl = template.Template(template_text)
return tpl.render(context)
Then in template
...
<a href="{{ node.get_url }}" class="nav-link"
{% for attr, value in node.link_attrs.items %} {{ attr }}="{{ value }}"{% endfor %}>
{% block node_label %}{% render_nested node.label %}{% endblock %}
</a>
...
Haven't tested but I think it will work.
More on template: https://docs.djangoproject.com/en/dev/ref/templates/api/#rendering-a-context
More on custom tags: https://docs.djangoproject.com/en/dev/howto/custom-template-tags/#writing-custom-template-tags
If I understand you well, you want to write template code that renders to template code and then be processed again. Something like ... meta-templates?
I can see you already figured out the first part, but now you need the resulting code to be parsed again in order to set the respective value for {{ request.user }}.
I achieve that by using middleware, but since parsing a template is an expensive operation I implemented some a mechanism to apply the "re-parsing" process just to urls/views of my selection.
The model.
class ReparsingTarget(models.Model):
url_name = models.CharField(max_length=255)
Simple enough, just a model for storing those URL names I want to be affected by the middleware.
The middleware.
class ReparsingMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
# We are no interested in whatever happens before
# self.get_response is called.
response = self.get_response(request)
# Now we will re-parse response just if the requested url
# is marked as target for re-parse.
if self._marked(request) and isinstance(response, TemplateResponse):
# Decode the template response code ...
content = response.content.decode('utf-8')
# Create a Template object ...
template = Template(content)
# Provide request to de context ...
context_data = response.context_data
context_data.update({'request': request})
# ... and renders the template back the the response.
response.content = template.render(Context(response.context_data))
return response
def _marked(self, request):
url_name = resolve(request.path_info).url_name
return ReparsingTarget.objects.filter(url_name=url_name).exists()
It is a really simple implementation, the tricky part for me was to figure out how to put the idea into Django code.
In practice.
Some model.
class Foo(models.Model):
label = models.CharField(max_length=255)
The template:
{% for foo in foos %}
{% comment %} Remember foo.label == '{{ request.user }}' {% endcomment %}
<p> Username: {{ foo.label }} </p>
{% endfor %}
The stored Foo instance:
And the result:

Data accessing & display in Django

I'm having trouble accessing database data in another template
different than django administration. In the administration page I
get results:
But when I try to display them in another template:
(No results available)
Here's how my urls.py admin page and template urls looks like:
urlpatterns = [
path('admin/', admin.site.urls),
path('lista/', views.entitats, name = 'lista_entitats')
]
Here's how my admin.py call to entity list and register looks like:
class EntitatAdmin(admin.ModelAdmin):
list_display = ('codi', 'nom', 'adreça', 'cp', 'correu', 'inspector')
inlines = [DiaLliureDisposicioInline, VisitesDirectorCentreInline, ExitEscolarInline, ObresCentreInline, OfertaEstudisInline, NEE_alumnatInline, FormacioInline, ProjectesInline, ProfessorsInline, DespesesFuncionamentInline]
search_fields=('nom',)
list_per_page=5
admin.site.register(Entitat, EntitatAdmin)
In my views.py this is how I ask for the template (and where I feel I'm not getting db information well):
from entitats.models import Entitat
def entitats(request):
lista_entitats = Entitat.objects.all()
context = {'llista_entitats': lista_entitats}
return render(request, 'entitats.html', context)
And finally my template, where I try to display the list of entities:
{% if context.llista_entitats %}
<ul>
{% for question in objects_list %}
<li>{{ question.question_text }}</li>
{% endfor %}
</ul>
{% else %}
<p>Ninguna entidad disponible.</p>
{% endif %}
Sorry if it's loong, I'll delete if there's something not necessary, and THANKYOU in advance.
You don't need context.variable_name syntax in template to check variable value, just use:
{% if llista_entitats %}
instead of
{% if context.llista_entitats %}
Also since your variable is llista_entitats it should be:
{% for question in llista_entitats %}
<li>{{ question.question_text }}</li>
{% endfor %}
Note I replaced objects_list with llista_entitats and entitat.id with question.id.

conflict between User and user.socialaccount in django-allauth

I have done this tutorial as it explained here:
and here
but there is some points that i can not understand.
When i log in using a facebook account i can get access also easily to my admin page and i want it to be happened (because it is not secure), so is there a way to fix that ?
If i want to bring that registred user to another template, i can do it only whith direct_to_template method in my url dispatcher, here is an example:
url(r'^tags$', direct_to_template, {'template' : 'user.html' }),
is there another way to do it.
Finally to be more clear, here is some snippets of my project:
urls.py
urlpatterns = patterns('',
#All Auth URLS
url(r'^accounts/', include('allauth.urls')),
url(r'^accounts/profile/', direct_to_template, { 'template' : 'profile.html' }),
#nav urls
url(r'^$','fb.views.home', name="home"),
url(r'^tags$', direct_to_template, {'template' : 'tags.html' }),
views.py
def home(request):
return render_to_response("base.html", locals(), RequestContext(Context))
base.html
.....
{% block body %}
{% block content %}
{% if user.is_authenticated %}
{{ user.username }} <p> you are logged in </p>
<p><a href="/accounts/logout/" >Logout </a></p>
{% else %}
<p> you are not authenticated : </p>
<a href="/accounts/facebook/login/" >Login with Facebook </a>
{% endif %}
{% endblock content %}
{% endblock body %}
...
profile.html
...
{% block content %}
{% if user %}
<h1>Welcome, {{user.first_name}}</h1>
<p>Following is the Extra information that facebook has provided to allauth:</p>
{% for account in user.socialaccount_set.all %}
<p>First Name: {{ account.extra_data.first_name }}</p>
<p>Last Name: {{ account.extra_data.last_name }}</p>
<p>Profile Link: {{ account.extra_data.link }}</p>
{% endfor %}
{% endif %}
Go to tags
{% endblock content %}
{% endblock body %}
tags.html
{{user.socialaccount_set.all.0.get_avatar_url}} <br/>
{{user.socialaccount_set.all.0.uid}} <br/>
{{user.socialaccount_set.all.0.get_provider_account }} <br/>
Finally thanks in advance for your help .
The secrect is:
After logging in, the user was hiding in the request object, so view shoukd be like this:
def home(request):
user = request.user
return render_to_response("base.html", locals(), RequestContext(Context))
Now, the problem is resolved, but i wonder why the Context User object was anounymous.
i am asking this question because that last user object woiuld have the same value of the request user in a simple authentication

Flask: current page in request variable

In a template, how do I get what page I'm currently on? I'd rather not pass a variable like page , especially when I know some request.xxx can provide me with the information.
<li {% if page=="home" %}class="active"{% endif %}>
Home
</li>
<li {% if page=="about" %}class="active"{% endif %}>
About
</li>
As long as you've imported request, request.path should contain this information.
Using request.path doesn't seem to be a proper approach since you'll have to update the paths in case of changing URL rules or deploying your site under a subfolder.
Use request.url_rule.endpoint instead, it contains actual endpoint name independent of actual path:
(Pdb) request.url_rule.endpoint
'myblueprint.client_pipeline'
In a template:
<li {% if request.url_rule.endpoint == "myblueprint.client_pipeline" %}class="active"{% endif %}>Home</li>
Good luck!
First import request from flask in your application. Then you can use it without passing to template:
<li {%- if request.path == "/home" %} class="active"{% endif %}>
Home
</li>
<li {%- if request.path=="/about" %} class="active"{% endif %}>
About
</li>
To avoid using hard-coded URLs you can use the url_for function like this:
{% for ni in ['index', 'foo', 'bar', 'baz'] %}
<li {%- if request.path == url_for(ni) %} class="active"{% endif %}>{{ ni | capitalize }}</li>
{% endfor %}
In this case index, foo, bar and baz would be function names, used like this in your python code:
#app.route('/')
def index():
Try
<li {% if request.endpoint == "blueprintname.routename" %}class="active"{% endif %}>Home</li>
This one worked for me.
You can also use .split if your url has more stuff in it.
Example:
/product
/product/add
/product/32432/edit
/product/32432/view
{{ request.path.split('/')[1] }}
This will return only "product"