Internationalizing images in django - python

How would I implement different images from static folder based on language?
For example, when visiting the main site the layout will load in english but when changed to japanese the logo and images attached to the layout will change based on the requested language. please help.....

You could create iso folders like:
/static/
/img/
/fr/
/en/
/us/
and create a template tag that returns a language iso prefix based on the locale setting, something like:
{% static "img"|append_i18n_prefix %}

In your template:
{% load i18n %}
{% get_current_language as LANGUAGE_CODE %}
Then for the logo etc:
<img src="{{MEDIA_URL}}{{ LANGUAGE_CODE }}/logo.png" alt="" />

You could pass a language parameter to your page template and use it as part of your media file URL.
This would require you to host all media files for, e.g., English in a folder SITE_MEDIA/english, while other, e.g., Japanese images would be available from SITE_MEDIA/japanese.
Inside your page templates, you could then use {{MEDIA_URL}}{{language}}/my-image.jpg...

Approach I recommend is to have your base template (let's say for example page.html) and then for the differences just extend that (i.e. page-fr.html)
Where the image needs to be different you have a template block, and then in the page-fr.html you can put in a different image in that block.
That way we support different languages if we have the image, but if we don't have the translated image yet it still uses the normal template. You can even provided different text/layout for different languages (if you want or need, some languages have extremely long texts which can change the layout of labels).
Then in the view we have it try load page-[locale].html if it exists (and we can make it fallback to page-[lang].html for stuff like fr-ca) and then finally falling back to page.html if it exists.
Template page.html:
{% blocktrans %}Some text{% endblocktrans %}
{% block image_one %}<img src='{% static "image_one.png" %}'>{% endblock %}
template page-fr.html:
{% extends 'page.html' %}
{% block image_one %}<img src='{% static "image_one-fr.png" %}'>{% endblock %}
Then in your view:
context = {'data': data}
templates = ['page-fr.html', 'page.html']
return render(request, templates, context)
You would replace the page-fr.html with some code that looked up the current language and did it. You could even make a simple template loader that would do this already (I would not be surprised if a django app hasn't got one)
The advantages to this are:
Usage of the static tag instead of media_url joining so all your static middleware works (like the hashed filenames)
You can override anything, not just images
The other techniques assumed the image would always exist for all locales, in this one it's only used if you define it, and you know what images you have. If you don't have the zh image yet for example, you can leave it as the english instead of getting a 404 (or if you have some, you can just do the ones you want).
I would really advise against the other answers here where you join up strings to produce the final content. You're creating dynamic urls to static content. Big risk of creating a url that might 404 if you don't have it. Also joining strings doesn't give you access to the static middleware (so no long cached hashed urls). You can run the final string through the static tag after joining though, but if that static doesn't exist it will have a server error which is worse.

Slight variation of Mikael's answer using get_static_prefix:
{% load i18n static %}
{% get_current_language as LANGUAGE_CODE %}
<img src="{% get_static_prefix %}path/to/image_{{ LANGUAGE_CODE }}.svg">

Related

How to load image from backend (SQL textfield ) directly by using Django?

I am trying to make a blogging website. I know django provides argument templates like
{% include images.html with value=sense %}
The above code directly works in HTML and hence everything works. The images are stored in a backend database and connected to everystory by some logic. The user can use the names of the images and call whenever they need to use it
When I try the above code directly in the backend it doesn't work because I think once something is rendered then it doesn't rerender by django HTML
I wish to paste some form of links in the django story backend. such that when it renders in HTML automatically the page should show pics in the appropriate place. If anyone has any idea how to do this kindly let me know.
So when loading stories in the database the user can put some form of links for images in the database and while rendering all images come in a certain format as specified in the block in the blog.So there can be any number of images and the count is not longer fixed as shown in the pics below where I am trying to render a image called sense from the backend which doesn't work.. whereas it directly works in the frontend.
<p>{{object.story_title}}</p>
<p>{{MEDIA_ROOT}}</p>
<p>{{object.story}}</p>
{% include "blogdescription/image.html" with value=sense %}
Thank you for your time.
with regards
Let me start saying that doing exactly what you want is not possible because Jinja will compile and render {{object.story}} and not its content (the include). It does not seem possible to use nested Jinja syntax to load any resources, includes, extends, urls, etc.
Which explains why when you place the include in the template it works but does not inside your model field.
What seems possible is to load an HTML image with a explicit URL to the resource, lets say, the content inside your text field is:
<div style="display: flex; justify-content: center; align-items: center;">
<img src="/static/myimage.jpg" alt="Object Image">
</div>
Template.html (source):
{% block content %}
{{obj.title}}
<br>
{{obj.body|safe}}
{% endblock %}
Alternatively, it is possible to generate a HTML file to render dynamically based on Object.field. Note that this solution is a heavy load on the server, for every request will generate a dynamic file to be rendered.
Obj field value:
{% extends 'base.html' %}
{% block content %}
{{obj.title}}
<hr>
{% include 'includes/image.html' %}
{% endblock %}
views.py:
def story(request, id):
obj = Story.objects.get(id=id)
f = open(f'templates/generated/dynamic_template.html', 'w+')
f.write(obj.body)
f.seek(0)
return render(request, 'generated/dynamic_file.html', {'obj': obj})

How to exclude a part of a Django template file from processing?

I have a Django template file that has a couple of enormous strings in it (images encoded in Base64). When I use the Django templating engine, it chokes and takes 5 minutes to render the template. Is there a way to exclude a part of a template, with something like:
{% ignore %}
<img src='....'>
{% endignore %}
Does this exist?
Use verbatim tag!
From django docs https://docs.djangoproject.com/en/dev/ref/templates/builtins/#verbatim
verbatim
Stops the template engine from rendering the contents of this block
tag.
A common use is to allow a JavaScript template layer that collides
with Django’s syntax. For example:
{% verbatim %}
{{if dying}}Still alive.{{/if}}
{% endverbatim %}

How to get absolute URL with domain and protocol in a Django template? [duplicate]

In Django, when I use:
{{ request.build_absolute_uri }}{% static "img/myimage.jpg" %}
It produces: 'http://myurl.com//static/img/myimage.jpg'. This produces an error.
How can I remove the double slashes?
The STATIC URL is:
STATIC_URL = '/static/'
But I don't think removing the first '/' would be a good idea.
The request object is available within your templates and you can easily access attributes such as request.scheme or request.META.HTTP_HOST to construct your base URL that you can prepend ahead of your static URL to get the full URL.
Final example would look something like this:
<img src="{{request.scheme}}://{{request.META.HTTP_HOST}}{% static 'img/myimage.jpg' %}">
The build_absolute_uri method builds an absolute uri for the current page. That means that if you're on e.g. 'http://myurl.com/login/', the resulted full url would be 'http://myurl.com/login//static/img/myimage.jpg'.
Instead, use request.get_host() (optionally together with request.scheme for the url scheme), or preferably, use the sites framework to set a template variable to the current site domain. The get_host() method has some issues regarding proxies.
The get_host() method will return the current domain without a path appended.
I just made a quick template tag for doing this. Create files /myapp/templatetags/__init__.py and /myapp/templatetags/my_tag_library.py, if you don't have them already, and add the following to my_tag_library.py:
from django import template
from django.templatetags import static
register = template.Library()
class FullStaticNode(static.StaticNode):
def url(self, context):
request = context['request']
return request.build_absolute_uri(super().url(context))
#register.tag('fullstatic')
def do_static(parser, token):
return FullStaticNode.handle_token(parser, token)
Then in your templates, just {% load my_tag_library %} and use e.g. {% fullstatic my_image.jpg %}.
In response to earlier comments wondering why someone would need to do this, my particular use case was that I wanted to put a link to a static file inside of an open graph protocol meta tag, and those links need to be absolute. In development the static files get served locally, but in production they get served remotely, so I couldn't just prepend the host to get the full url.
Is this worth an update (Django 2+)?
This helped me specifically because I was trying to put a query in the link, i.e. the myimage.jpg was actually pulling from the DB. I needed a way to put it in the src, which was to replace 'myimage.jpg' with {{ img_link_field_in_model }}.
<img src="{% get_static_prefix %}img/myimage.jpg">
will produce:
<img src="/static/img/myimage.jpg">
The example of the query is:
<img src="{% get_static_prefix %}img/{{img_link_from_model}}">
Use this for apps:
{{ request.build_absolute_uri|slice:":-1" }}{% static "img/myimage.jpg" %}
Use this generally:
{{ request.scheme }}://{{ request.META.HTTP_HOST }}{% static "img/myimage.jpg" %}
Not entirely sure what you're asking, but since the {% static .. %} is only adding /static/ to the front of your path you specify, you could just do that yourself:
{{ request.build_absolute_uri }}static/img/myimage.jpg
Not very modular, but then again most times you don't need direct access to the full url since it will just append it onto whatever url you're at if you use it as a src for some html object.
build_absolute_uri takes the location as an argument which handles the double slash problem.
Unfortunately you cannot pass arguments via the django template language.
You will need to build a custom template tag or filter which accepts an argument to the build_absolute_uri function.
One of the many reasons I prefer Jinja as I can just do this:
{{ request.build_absolute_uri(static('img/foo.png')) }}

jinja2 set background image

I am trying to set the background image using jinja2. I have managed to serve my file from my dev server and can post the image in the document, but I want it to form a nice background with everything else on top.
As an example, I tried this :
{% extends "layout.html" %}
{% block body %}
{% if current_user.is_authenticated %}
{% if commPageData.background_image %}
<body background="{{'/images/'+commPageData.background_image}}">
{% else %}
<body>
{% endif %}
A thing
</body>
I have a css file and a layout file that gives the default behaviour for a template. How can I have a nice background image which I am serving?
You seem to be trying to tell the front end to use application routing without passing it the right commands. I'm assuming you're using Flask. Really, there are two ways (that I can think of) to slice this bread, and it just depends on you. The first is just using standard html and not embedding python to route the app to look for the file, and looks like:
<body background="/path/to/image.jpg">
But, if you want to take advantage of the framework and the template, then you should use the built in method url_for
It looks something like this:
<body background="{{ url_for('static', filename=commPageData.background_image) }}">
'static' being the directory in the application where this image lives.
Now, I'm not sure where commPageData.background_image is coming from in your app. My code snip assumes it is being served as a value it will recognize if passed back to the logic, if that makes sense, and it needs to be where you tell the url_for method looks for it, even when dynamically generated. If you actually have a specific image you want to render as the background, it needs to be specified appropriately:
<body background="{{ url_for('static', filename='image.jpg') }}">
Of course, has been deprecated in HTML5 and may not render appropriately in many browser. It is much preferred to use CSS instead with
<body style="background:url({{'images/'+commPageData.background_image}});">
or put it directly in your CSS file

How to build the requests handlers when the JInja template has multiple blocks?

I'd like to make a simple website running on the GAE framework/service. It's very small, and i don't really need the whole powerful Django framework, and thus i'm opting for the google-made Webapp2 framework, coupled with the Jinja2 templating langage.
I'm coming from a really bare-PHP-and-HTML-oriented background, so I have a hard time adjusting to the way a real framework works. My current greatest interrogation comes from how the templating system and the request handlers are working together, especially if the the page's template has several "dynamic" elements.
I'll first explain what I used to do in PHP, so you may better understand what i want to achieve.
Let's say I want a website with :
a page title depending on the page being visited, eg : "Mysite.com | Control Panel"
a dynamic menu bar, that may change depending on the user's profile or logged-in status
obviously, a page body that completely depends on the page being viewed
The way i'd do it in PHP is thus here compressed into a simple example, index.php:
<?php
/*here use the $_GET or $_POST variable, and the $_SESSION variable
to figure out who's connected, which page is being displayed,
and store those values in global variables, for the
included modules to use */
include('page_header.php'); // renders the whole <head> </head> tag and its content
echo "<body>";
include('views/menu.php'); //generates the menu, displays it
switch($page_name){
case "home":
include('home.php'); //renders the page body for the homepage
break;
case "articles":
include('home.php'); //renders the page body for the blog articles listing
break;
case "guestbook":
include('home.php'); //renders the page body for the guestbook
break;
}
echo "</body>";
Each included module, using variables from the script that called them (index.php), and the $_POST, $_GET, $_SESSIOn superglobals, figures out what to display, and renders it to HMTL. here index.php also does some kind of very basic routing, using the switch statement.
Now,back to webapp2 and jinja2 framework:
I understand that, to have a modular approach to build a web page with Jinja, you need to use block structures, and extend those blocks. Thus, to build a similar page to the previous PHP example, i made the following template base.html:
<html>
<head>
<link rel="stylesheet" href="/static/css/reset.css">
{% block title %}
{% endblock title %}
</head>
<body>
<div class="menu">
{% block menu %}
{% endblock menu %}
</div>
<div class="body">
{% block content %}
{% endblock content %}
</div>
</body>
</html>
What i don't understand, is how you you'll build the different Handlers that, in turn, generate the context that Jinja will use to render the blocks, and avoiding redundency.
**Also, can I use several different template files that, alone, extend only one block (eg: menu.html, header.html, body_home.html, body_articles.html, ...) **
You can use as a base to answer, this example, from a small example that almost taught me all i needed to know.
Thanks for any help provided, sorry for any grammatical errors, english's not my native tongue.
There's a feature in jinja2 called macros which is pretty much a parameterized include.
So if the includes should be parametized, you would do:
{% macro menu(params) -%}
do something
{%- endmacro %}
And call the macro in your template:
<div> menu('bar') </dib>
If it is not necesary to provide parameters just leave it as static html in the parent template.
For the handler you can follow App Engine hello world example, just use your link to guide you to load jinja's enviroment.
I know you want to translate the php example, but try to do as much logic as posible in your handler instead of the template.
To your second question, yes you can extend just one block if you want, and if you need the parents content there's a {{super()}} block to get them.

Categories