Determining Site Language in Django Model [duplicate] - django

How can I get the current language in the current thread in a model or in the admin?

Functions of particular interest are django.utils.translation.get_language() which returns the language used in the current thread. See documentation.

Or you can also get this in your views
request.LANGUAGE_CODE

Be careful of the method you use to get the language. Depending on which method, Django will use different ways and informations to determine the right language to use.
When using the django.utils.translation.get_language() function, it's linked to the thread language. Before Django 1.8, it always returned settings.LANGUAGE_CODE when translations were disabled. If you want to manually override the thread language, you can use the override() or activate() functions, which is not very explicitly named, but well, still useful:
from django.utils import translation
with translation.override('fr'):
print(_("Hello")) # <= will be translated inside the with block
translation.activate('fr') # <= will change the language for the whole thread.
# You then have to manually "restore" the language with another activate()
translation.activate('en') # <= change languages manually
If you want django to check the path and/or request (language cookie, ...), which is a lot more common e.g. www.example.com/en/<somepath> vs www.example.com/fr/<somepath>, use django.utils.translation.get_language_from_request(request, check_path=False). Also, it will always return a valid language set in settings.LANGUAGES
I found it not very easy to find these differences through Google about this subject so here it is for further reference.

Just to add that if you do use django.utils.translation.get_language() then you should bear in mind that if that section of code will be called asynchronously (e.g. as a celery task) then this approach won't work due to it running in a different thread.

You can use these template tags in Django's templating language:
{% load i18n %}
{% get_current_language as LANGUAGE_CODE %}
Current language code: {{ LANGUAGE_CODE }}<br>
{% get_current_language_bidi as LANGUAGE_BIDI %}
{% if LANGUAGE_BIDI %}RTL <br>{% endif %}
{% get_language_info for LANGUAGE_CODE as lang %}
Language code: {{ lang.code }}<br>
Name of language: {{ lang.name_local }}<br>
Name in English: {{ lang.name }}<br>
Bi-directional: {{ lang.bidi }}
Name in the active language: {{ lang.name_translated }}

You can read the system's locale for language information.

Related

setting LANGUAGE_CODE in template based on page setting

In Django / Wagtail I can set the language of a single page. With my custom instance method {{ page.get_language }} this language is available in the template.
But I want all dates and hard-coded texts translated in the set language. So I would like to to set LANGUAGE_CODE with page.get_language.
Any ideas what the best practice is?
<html class="no-js" lang="{{ page.get_language }}">
and in your template {% load i18n %}
The django.utils.translation.activate function selects the language to be used by Django's translation framework, in preference to the default one in LANGUAGE_CODE - so, in this case you would use activate(page.get_language).

how to stop django template code from escaping

Is there any way to completely turn off django auto_escaping when rendering a template within the view code (for an email for example):
from django.template import Context, Template
subject_template_string = "Hi {{ customer.name }}"
subject_template = Template(subject)
context = Context({'customer':MyCustomerModel.objects.get(pk=1)})
subject = subject_template.render(context)
If customer.name is something like "Jack & Jill" - the subject looks like "Hi Jack &\amp; Jill" (without the backslash!)
is there something like
subject = subject_template.render(context, autoescape=False)
edit: The actual templates are created by the client in the database, I'm hoping to avoid having to say add |safe to all templates where this might happen...
Disabling it globally is usually a bad idea since you can easily forget it. I would recommend using the templatetag to disable it for that portion of your template instead.
Something like this:
{% autoescape off %}
This will not be auto-escaped: {{ data }}.
Nor this: {{ other_data }}
{% autoescape on %}
Auto-escaping applies again: {{ name }}
{% endautoescape %}
{% endautoescape %}
How about using mark_safe:
Explicitly mark a string as safe for (HTML) output purposes. The
returned object can be used everywhere a string or unicode object is
appropriate.
It marks a string as safe, so, you should take customer.name out and pass to the template:
from django.utils.safestring import mark_safe
customer = MyCustomerModel.objects.get(pk=1)
context = Context({'customer_name': mark_safe(customer.name)})
subject = subject_template.render(context)
Though, control what is safe or not is better to do inside the template itself, that's why using autoescape should be preffered.
Use Django's autoescape tag:
{% autoescape off %}
{{ body }}
{% endautoescape %}
for more info, check out the docs here.
This is untested, but based on source code review it looks like the context object can take autoescape as a key.
context = Context({'customer':MyCustomerModel.objects.get(pk=1), 'autoescape': False})
subject = subject_template.render(context)
That said, that's a pretty sweeping change. If you know what values the templates might be looking for, it's probably better to use mark_safe on those values and pass in the predefined options. That would have the added benefit of not risking the possibility of the client template calling a method with side effects on the customer. The first time someone writes a template and puts in {{ customer.delete }}, you have a problem.
Just came back to answer my own question with a simple solution, and there were already 4 answers.. thanks.
This is what I've gone with:
subject_template = Template(u'{%% autoescape off %%}%s{%% endautoescape %%}' % email.subject)

Using the Django assignment_tag built-in tag the right way

I'm working on a project in Django.
Earlier today, I discovered the new (Django >= 1.4) assignment_tag. I immediately decided that it was just what I needed EVERYWHERE and threw some logic into one that executed a very simple query against the database and returned the resulting queryset. The function I wrapped takes an argument that allows the invoking context to specify how many results to grab, directly in the template when I am using the template tag.
It is quite convenient - I don't have to update my view when I decide this list should have 5 items, not 3 - but it seems like one of those gray areas where we aren't supposed to tread (i.e. pushing application logic into templates) when writing good, maintainable Django code.
Now, a couple of hours separated from writing the code, I'm wondering if I should scrap the assignment_tag entirely.
Code:
models.py:
class SomeObject(models.Model):
is_active = models.BooleanField(default=False)
(...)
templatetags/myapp_tags.py:
from django import template
from myapp.models import SomeObject
register = template.Library()
#register.assignment_tag
def get_someobjects_list(max_results=0):
queryset = SomeObject.objects.filter(is_active=True)
if max_results == 0:
return queryset
elif max_results > 0:
return queryset[:min(max_results, queryset.count())]
else:
return None
templates/myapp/chunks/someobject_list.html:
{% load myapp_tags %}
{% get_someobjects_list as someobjects_list %}
# or {% get_some_objects_list 5 as someobjects_list %} ... flexible!
{% if someobjects_list %}
<ul>
{% for someobject in someobjects_list %}
<li>
<a href="{{ someobject.get_absolute_url }}">
{{ someobject.name }}
</a>
</li>
{% endfor %}
</ul>
{% else %}
<span>No someobjects exist</span>
{% endif %}
I was really excited to discover these existed - it's convenient for me in this particular case. Now that my excitement over finding a new feature has passed, it seems pretty clear that I'm misusing it. The example given in the Django docs seems like a better application of this - grabbing the string representation of current datetime, something that doesn't require a DB query. My worry is that I'm setting myself up for heartache if I start using this pattern regularly. Following the slippery slope all the way down: I'll end up not even bothering to pass a context to my templates and ALL my DB queries will be hidden away in template tags where nobody would think to look for them.
It seems the code would be cleaner if I just threw out this whole "great idea" I had when I discovered assignment_tags and created a custom model manager instead.
Are there other clean ways of accomplishing this that I am missing? Are manager methods the consensus best way among Django developers?
assignment template tags are especially helpful if you need to get some information into the template context for a few pages of a website, but don't want to (or can't) put the info into every view on the website, and don't want to or can't rely on a context processor.
they basically guarantee that your information will be available in the template.

Is there any way to distinguish between two templatetags that have the same name?

I have 2 different template tags that share the same name: the_template_tag.
Is there any way to distinguish between the two template tags? Something like "source1.the_template_tag" and "source2.the_template_tag"?
Here is my case. I am using django-timezones. There is a templatetag called localtime that basically allows me to display the date in the client local time.
{% load timezone_filters %}
... some more code
"user_localtime": "{{ serverdate|localtime:user_timezone }}",
Also, I am using the new timezones of Django 1.4. When I need to use the client local time (with the django-timezone), then I start to have problems. Basically, I have to turn off the timezones of django:
{% load tz %}
... some more code
{% localtime off %}
But the templatetag is the same. Then, of course, I get an error when I try to use both:
{% load tz %}
{% load timezone_filters %}
... some more code
{% localtime off %}
"user_localtime": "{{ serverdate|localtime:user.user_timezone }}",
You have two options:
Stop using django-timezones and use the timezone features of django 1.4
If you must use django-timezones, edit the source and rename the tag.
I would highly recommend #1, and strongly discourage #2.

Django: Display current locale in a template

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.