Django: Display current locale in a template - django

I need to embed the current locale in a Django template's output (as part of a URL to be precise). I know that I can access the current language as {{ LANGUAGE_CODE }} if I { load i18n } but is there a similar way to access the current locale?
I suppose I could use to_locale() in the view logic and put it in the context for the template, but I'm looking for something more generic that might be part of the Django framework itself. Is there such a syntax?

I solved this by including code below in the template
{% load i18n %}
{% get_current_language as LANGUAGE_CODE %}
and the variable LANGUAGE_CODE has the value you want (see also django docs for an example usage).

You might want to write your own context processor, which would call to_locale and automatically populate the context with the result -- it would just be something like this.
from django.utils.translation import to_locale, get_language
def locale(request):
return {'LOCALE': to_locale(get_language())}

I thought of implementing my own custom template tag that would simply output to_locale(get_language()) but the answer above is easier to implement so I like it better.

Related

Django template: How to pass formatted string to include tag

I am new to Django and Django template, I know Django Template is kind of restrictive compare to Rails.
So I am including a template in email like:
{% include "./partials/_info_row.html" with value=f'{request_count} requests' %}
but this throws error: TemplateSyntaxError: Could not parse the remainder: ''{request_count} requests'' from 'f'{request_count} requests''
Is there a way to pass formatted string like this to include tag?
Exception is raised because you can't use f-strings in Django templates - templates language is not actually a Python.
According to doc's there is not need to explicitly pass context variable when using include:
Loads a template and renders it with the current context.
If you need to pass a combined value (context plus something else like "requests" string), you can use simple tag:
tags.py
#register.simple_tag(takes_context=True)
def your_custom_tag(context, format_string):
request_count = context['request_count']
return f'{request_count} requests'
templates
{% with r_count=your_custom_tag %}
{% include "./partials/_info_row.html" with value=r_count %}
{% include "./partials/_info_row.html" with value=request_count|stringformat:'s'|add:' requests' %}
request_count|stringformat:'s' - convert number to string
some_var|add:'requests' - concat strings
Thanks #Chamel and #crazyzuber. I used combination of your answers. Created custom filter.
I knew about custom tag. But I wanted to avoid that because this was not generic tag, it will get used only at one place, so I wanted a solution for which I dont have to write custom tag. But custom tags solution works because it allows you to format string in anyway, which was not possible using existing built-in.
Btw I used #register.filter
#register.filter(is_safe=True)
def request_count_text(count):
return f"{count} request{ 's' if count > 1 else '' }"
and using it as:
{% include "./_info_row.html" with value=request_count|request_count_text %}
This solves my issue.

djangocms-snippet which contains {% %} doesnot show up as placeholder content

I am trying to make my footer a editable from frontend.. using placeholder and inserting footer snippet.
yet, my footer snippet contains django template language
e.g.
Terms and Conditions
as a result, the placeholder content is not showing up, if i remove the django specific things
Terms and Conditions
it is working.
how can I make it work with django reverse url?
I could have given hard coded path but i want the path translatable so i need to reverse by url's name.
If I've got you right, just create custom tag and store templates in database:
from django.template import RequestContext, Template
#register.simple_tag
def footer(request):
snippet = Snippet.object.get(name='footer')
template = Template(snippet.html)
return template.render(RequestContext(request))
{% footer request %}
use this syntax:
{% url 'terms_conditions' as the_url %}
Terms and Conditions
use smartsnippets
These has the capability of rendering django tags

how do i use isinstance() in django template language [duplicate]

Is there a way to do isinstance/issubclass in a Django template? I realise I can write my own templatetag, but I'm surprised this isn't possibly which makes me think I'm either doing something wrong or missing something obvious.
I wish to display two different segments of markup, depending on which type of item I'm displaying whilst iterative over my collection. Thanks!
I think a simple template filter here fits the best. It is really quick to implement and easy to call. Something like this:
in templatetags/my_filters.py:
from django import template
from django.utils.importlib import import_module
register = template.Library()
#register.filter
def isinst(value, class_str):
split = class_str.split('.')
return isinstance(value, getattr(import_module('.'.join(split[:-1])), split[-1]))
in your template:
{% load my_filters %}
...
{% if myvar|isinst:"mymodule.MyClass" %}
...do your stuff
{% endif %}
Although the above is a sample code (not tested), I believe it should work.
For more information on custom template filters please see the django documentation
EDIT: Edited the answer to show that the filter argument is actually a string and not a python Class
If all of these inherit from a common base type, but you need to know which type it is, you may want to just implement a method on the base that returns the type - then you can call if foo.get_type == 'type1' (or whatever) in your template.
You are missing something here: the only logic in the template is supposed to handle template rendering. isinstance / issubclass clearly smell like view logic, and should be in the view. If the template rendering depends on those functions (which I guess it does), you should implement the logic in the view, and just pass the template what it needs to know:
# in the view:
if isinstance(some_obj, SomeClass):
do_fancy_template_stuff = True
else:
do_fancy_template_stuff = False
# in the template:
{% if do_fancy_template_stuff %}
<fancy_template_stuff />
{% endif %}
Remember: the django templating engine was created having non-programmers, like designers, in mind.

django extends different base templates

I understand we can use "extends variable" in the template to switch between two different extended templates.
e.g.
views:
if something:
base = 'base1.html'
else:
base = 'base2.html'
return render_to_response ('template.html', {'base':base})
template.html:
{% extends base %}
Normally that works fine. However, my problem is that I am using django-registration of which I don't have to write my own view to handle the registration and login process. That also means that I am not able to pass the variable to the template. Though I do have the registration templates under my project directory. (like login.html)
Unfortunately, Django can't do this in the template:
{% if something %}
{% extends 'base1.html' %}
{% else %}
{% extends 'base2.html' %}
{% endif %}
The only way I know that the 'variable base' can be passed down to the auth-login is to write my own views like login, logout,etc. This seems like not fitting the DRY model and fairly error prone going forward.
Is there another way that I can accomplish this? Or any pointers to workaround the problem?
Thanks.
-P
If it's just 2 (or 3) options where that 'something' can be made to a Boolean, then you could use the yesno filter:
https://docs.djangoproject.com/en/dev/ref/templates/builtins/#yesno
So:
{% extends something|yesno:"base1.html,base2.html" %}
If you want something a bit more free-form, then you could make use of the extra context / custom context processor option mentioned above, and try something like:
{% extends selected_template|default:"base2.html" %}
where selected template is just the path to whatever base template you like.
To be honest this looks to me like a code smell - I've used django-registration a few times, I work on quite large sites and I never needed to extend a template from another template which is only known at run time.
Anyway, if you really want to pass a custom variable to a template rendered by 3rd party module, and you don't want to hack that module, then you have to use e.g. custom template context processor. Also, django-registration allows extra_context to be passed to its views, maybe that would be enough. You can also try monkey-patching. Or maybe you can try manipulating template folders or template loaders to get what you need.
But all these things are IMHO hacks and you shouldn't use different templates for one view, unless it's a generic view.
I think you should not place differences between the templates into the selection of different base templates. Having different base templates is what violates the DRY principle. Place the common things into a template, ie. registration.html, the differences into other templates that you call via 'include':
{%extends base.html%}
{%if something%}
{%include "type1.html"%}
{%else%}
{%include "type2.hmtl"%}
where the template names are the same as you would use in the view definition.
This probably isn't what you are looking for, but could you just include your conditionals in your base.html?

Django templates, pass template language through a template variable

I was thinking about putting my static pages in the database (simple model of url, title and content) and then having a basic base_static.html template - making them super easy to edit (from admin interface) if necessary.
I know you can easily escape html like so:
{{ content|safe }}
or
{% autoescape off %}
{{ content }}
{% endautoescape %}
But I need to be able to use some of the template language in the static pages, e.g. a simple for loop to go over variables passed to it from the view.
Is this possible, or would you recommend simply using templates to serve the static pages?(They won't change that much ever)
Thank you for your help.
If you want to store templates in db (and that is what you want if you want to use a template language) you can use this app : django-dbtemplates.
Check this question: Extending Django Flatpages to accept template tags
You may get some ideas from the solution exposed there