I am using Django and developing an i18n site serving many languages. I want to make a modal that stays in base.html, so that users can switch the language wherever they are.
I managed to do something like this.
<div class="modal-body">
{% get_available_languages as languages %}
{% for lang_code, lang_name in languages %}
{% language lang_code %}
{{lang_code|lang_name}}
{% endlanguage %}
{% endfor %}
</div>
Which turns out urls like:/ja/, /en/, /fr/, etc..
but this kind of approach links to the main page only.
When using {{request.path}} or {{request.get_full_path}} for the url like:
{{lang_code|lang_name}}
It doesn't include the i18n url patterns..
Is there any way for directing current url with request.path??
TARGET
When in /foo/ : /ja/foo/ /en/foo/ /fr/foo/
When in /bar/ : /ja/bar/ /en/bar/ /fr/bar/
Thanks in advance!
This topic is discussed in this SO question: Django templates: Get current URL in another language.
In my project, I use this simple template tag (taken from https://djangosnippets.org/snippets/2875/), which returns the URL of the current view in another language.
foo/templatetags/i18n_urls.py:
from django import template
from django.urls import translate_url
register = template.Library()
#register.simple_tag(takes_context=True)
def change_lang(context, lang: str, *args, **kwargs):
path = context['request'].path
return translate_url(path, lang)
some_template.html:
{% load i18n_urls %}
<ul>
<li>
EN
</li>
<li>
CS
</li>
<li>
DE
</li>
</ul>
Please note that translate_url function is not documented in the official Django docs. Here is the source code of this function: https://github.com/django/django/blob/master/django/urls/base.py#L161-L181.
Related
When I tried to iterate through a list of post titles to create links in a django template the urls never match the requested path (matching the current web page should alter the formatting on the page for that list item). When I try and change things, Django spits out a 404 error which doesn't let me diagnose the problem or it "works" but not as expected.
the relevant url patterns (in blog app within project):
path('', views.index, name='blog_index'),
path('<slug:post>', views.blog_post, name='entries')
the relevant views functions (in blog app within project):
ef index(request):
try:
return render(request, 'blog/index.html', {'posts':blog_posts.keys})
except:
raise Http404()
def blog_post(request, post):
try:
return render(request, 'blog/post.html', {
'post_title':post,
'post_content':blog_posts[],
'posts':blog_posts.keys
})
except:
raise Http404()
the navigation template:
<ul>
{% for post in posts %}
{% url "blog:entries" "{{post}}" as blog_entry %}
<li><a href="/blog/{{post}}" {% if request.path == blog_entry %} class="active"{% endif %}>
<span class="item">{{post}}</span>
</a></li>
{% endfor %}
</ul>
I suspect the {% url "blog:entries" "{{post}}" as blog_entry %} in the template is not resolving correctly as when I replace the href with {% blog_entry %} it causes a 404 error.
I have tried hard coding it in, I have tried different ways of writing the url, I have tried changing the syntax (in case I am doing it incorrectly. I have checked the page source when I have run tests. I have never been able to get the class attribute to be "active" when on the matching page.
EDIT: The links all go to the correct pages, however the IF logic in the template does not work. i.e. None of the changes I have tried make result in reques.path == blog_entry resolving as True.
Also the above code snippets are part of an App within a project and I have included more of the views.py and urls.py file. Currently I have the "blog posts" stored in a dictionary at the top of views.py for testing.
Try this:
<ul>
{% for post in posts %}
{% url "blog:entries" post=post as blog_entry %}
<li><a href="/blog/{{post}}" {% if request.path == blog_entry %} class="active"{% endif %}>
<span class="item">{{post}}</span>
</a></li>
{% endfor %}
</ul>
So I am new to Django (and complete the 7 part tutorial) as well as read the flatpages app documentation.
At the end of which, whoever wrote the Django documentation gives a demonstration as to how one would retrieve all the flatpages:
{% load flatpages %}
{% get_flatpages as flatpages %}
<ul>
{% for page in flatpages %}
<li>{{ page.title }}</li>
{% endfor %}
</ul>
I now have flatpages working (e.g. if I go to /pages/my_flatpage/ the default template I have renders. as I have included url(r'^pages/', include('django.contrib.flatpages.urls')) in the urlpatterns.
So I am now in another app of mine and want to link to these flatpages. Using the code above I create the links. However, when I click on them, they do not render as they are routed to /my_flatpage/ rather than /pages/my_flatpage/.
So I tried including the url pattern in my app, but that didnt work. How can I get the to go to the right place?
Since you're not hosting the pages directly at the root, the url attribute doesn't return the whole path. Instead you should use the URL reversing functionality as with any other object:
{% for page in flatpages %}
<li>{{ page.title }}</li>
{% endfor %}
I'm a beginner in django-oscar and I try to manage a new view on the page.
I've already created two pages with django-oscar dashboard,
https://ibb.co/cM9r0v
and made new buttons in the templates:
Lib/site-packages/oscar/templates/oscar/partials/nav_primary.html
https://gist.github.com/Kalinar/076fc8144869c3b50fc0bc9e52f825e4
I have no idea how to make a good a href="???" to new pages in buttons ... can someone help?
Maybe there is better way to do it, can you explain it to me?
Oscar uses Django's flatpages app, so you can use their template tags to dynamically add in navigation links to the pages you create.
{% load flatpages %}
{% get_flatpages as flatpages %}
{% for page in flatpages %}
<li class="dropdown active">
<a href="{{ page.url }}" class="dropdown-toggle" {% if not expand_dropdown %} data-toggle="dropdown"{% endif %}>
{% trans page.title %}
</a>
</li>
{% endfor %}
You can find more information on the flatpages app in the Django flatpage documentation.
You already know the title and of course the id of the page, and each page is an instance of the model PagePromotion, just query the model for such name/id and use the attribute page_url of the returned instance to send it within a variable in the context of the view that renders the menu.
Then in the template:
href="{{ variable_containing_url }}"
I am trying to make a recent article list in the sidebar of my blog. So I make a tag in templatetags.
I use django1.8 and python2.7.
templatetags/blog_tags.py
from ..models import Article,Category
from django import template
from django.utils.safestring import mark_safe
register = template.Library()
#register.simple_tag
def get_recent_articles(num=5):
return Article.objects.all()[:num]
base.html
{% load blog_tags %}
<!DOCTYPE html>
...
<div class="widget widget-recent-posts">
<h3 class="widget-title">recent</h3>
{% get_recent_articles as article_list %}
<ul>
{% for article in article_list %}
<li>
{{ article.title }}
</li>
{% endfor %}
</ul>
</div>
When I runserver,Template error,Traceback display the problem line is {% get_recent_articles as article_list %}
TemplateSyntaxError at /blog/index/
'get_recent_articles' received too many positional arguments
How do I solve this error? Please give me some advices.
Any help will be much appreciated.
The ability for simple tags to store their results in a variable was added in Django 1.9.
In previous versions, you should use the assignment_tag decorator instead.
I have three apps in my Django project that correspond to separate parts of the website. All three parts are accessible from the navigation menu, defined in common base.html template.
I want to be able to identify the app that called the template to add an 'active' css class to the menu option corresponding to the active part of the site.
What's the best way to do it, short of modifying each view to pass an additional variable to the template?
The most non-invasive way would be:
Write a template tag that generates your menu.
Update your context with the application name.
Pass this to the template tag and modify the css accordingly.
I'll explain the second bit, as writing custom template tags is covered in detail in the django documentation.
To update the context; we need some middleware. This should do what you need:
class SetApplicationName(object):
def process_view(self, request, view_func, view_args, view_kwargs):
request.current_app = view_func.__module__.split('.')[0]
Place this somewhere django can find it (in any directory in PYTHONPATH), and add it to your middleware classes. Also, make sure you have django.core.context_processors.request in your template context processors.
In your templates, now you have {{ request.current_app }} which should point the app name.
Your template tag should be something like {% navigation_menu request.current_app %}, and you can then modify your menu css accordingly.
I would try "overriding" the {%block%} tag.
In your base.html template put something like:
{%block navigation_bar%}
<div class="regular">First app</div>
<div class="regular">Second app</div>
<div class="regular">Third app</div>
{%endblock%}
In your descendant templates, change that navitation_bar block with other. first_app_base.html looks like:
{%extends "base.html"%}
{%block navigation_bar%}
<div class="active">First app</div>
<div class="regular">Second app</div>
<div class="regular">Third app</div>
{%endblock%}
If you define navigation menu in separate template, you could include it with additional context.
base.html:
{% block navigation %}Here will be navigation{% endblock %}
template_from_some_app.html:
{% extends "base.html" %}
{% block navigation %}
{% include "navigation.html" with active_app='second_app' %}
{% endblock %}
navigation.html:
<ul class="nav">
<li {% if active_app == 'first_app' %} class="active">{% endif %}>
First app
</li>
<li {% if active_app == 'second_app' %} class="active">{% endif %}>
Second app
</li>
<li {% if active_app == 'third_app' %} class="active">{% endif %}>
Third app
</li>
</ul>