Django: escaping translations with safe - html

I've got a problem. When I use HTML Tags in a translation (.po files) they end up being displayed as: <p>. When I use the |safe filter it results in <p>. But I don't get it to work that the actual html tags are passed.
Anyone got a clue about this?
.po file:
#: website/views.py:35
msgid "web_content_detailed"
msgstr "<h1>asdjkasjdlas</h1>"
view.py:
context = {}
context['somevar'] = _('web_content_detailed')
return render(request, 'somehtml.html', context)
somehtml.html:
{{ somevar }} => <h1>asdjkasjdlas</h1>
{{ somevar|safe }} => <h1>asdjkasjdlas</h1>`

Related

Django How to make the condition correct on an HTML page - search bar

I try to do a search engine if the word in my DB thah I created then display the word on the HTML page and if not then nothing.. I did it right in VIEW but I can not apply it on the HTML page I searched the internet and did not find an answer I'm sure I fall for something stupid.
This is the view
def Search_word(request):
search = request.POST.get("search") #Grab the search item
return render(request,"search_page.html", {"search":search})
this is the html:
{%for i in Word.English_word%}
{%if search in Word.English_word%}
{{search}}
{%endif%}
{%endfor%}
and the urls:
path("Search_page",views.Search_word ,name="Search-page"),
models:
class Words(models.Model):
English_word = models.CharField(max_length=30)
Hebrew_word = models.CharField(max_length=30)
How_To_Remember = models.CharField(max_length=40)
Name = models.CharField(max_length=20)
pub_date = models.DateTimeField()
The problem is that even if the word is valid it does not show me anything ..
You should implement the filtering logic in the view, not in the template. Templates are for rendering logic, not business logic. Furthermore one should filter with the database, since databases are designed to do this.
The view thus looks like:
def Search_word(request):
search = request.POST.get('search')
items = Word.objects.filter(English_word__contains=search)
return render(
request,
'search_page.html',
{'search': search, 'items': items}
)
and then in the template we render this with:
{% for item in items %}
{{ item.English_word }}: {{ item.Hebrew_word }} <br>
{% endfor %}
You can use as lookup __contains to check if the English_word has a substring that is equal to search, with __icontains you check case-insensitive, with __iexact you look for Words that match search case-insensitive, and finally you can filter with Engish_word=search for an exact match.

DJANGO template tags in plain text not displaying

I am making an app that displays questions. The question model has a text field and an image field. Each question has a template that is stored in my database in the text field. My problem is when I want to access images from the model, template tags are displayed as text and not rendering. My code:
# question model
class Question(models.Model):
question_text = models.TextField()
question_image = models.FileField(upload_to='static/images/questions', blank=true)
# question view
def question(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request, 'questiontemplate.html', {'question': question})
# template
{% extends 'base.html %}
{% load static %}
{% autoscape off %}
{{ question.question_text }}
{% endautoscape %}
# in my database:
question.question_text = '<p> some html
{{ question.question_image.url }}
some html </p>'
question.question_image = 'image.png'
This works fine and renders the html perfectly except the template tag is not rendered and does not not give the image url
I want this to be the output:
Some html
static/images/questions/image.png
some html
But instead this is the output:
some html
{{ question.question_image.url }}
some html
Any suggestions to how the template tags could be render from the database text would be much appreciated.
Thanks for reading
Django doesn't know that the content in your model field is itself a model. The template can't know that. The only way to make this work is to treat that field itself as a template, and render it manually.
You could do that with a method on the model:
from django.template import Template, Context
class Question(models.Model):
...
def render_question(self):
template = Template(self.question_text)
context = Context({'question': self})
rendered = template.render(context)
return mark_safe(rendered)
Now you can call it in your template:
{{ question.render_question }}

how to get the data from view to templates?

i'm trying to get the data from my views.py to the html page.
if the views.py code is this
def VerifiedBySuperuser(request):
if request.method == 'POST':
vbs = MaanyaIT_EXAM48_ManageQuestionBank()
vbs.QuestionID = MaanyaIT_EXAM48_ManageQuestionBank.objects.get(QuestionID=request.POST.get(QuestionID, None))
vbs.QuestionInEnglishLang = request.POST.get('QuestionInEnglishLang', None)
vbs.save()
else:
return render(request, 'exam48app/verifiedbysuperuser.html')
then what shoud the code of html page to view my all data to the tamplates..
this is my html page
<form class="from-horizontal" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="post-entry">
{{ MaanyaIT_EXAM48_ManageQuestionBank.QuestionInEnglishLang }}
</div>
</form>
now what should i do?
From your comment, you need to know How to write/render the data from view to html template
I will demonstrate a simple example for you,
Assuming you have a view as below,
def VerifiedBySuperuser(request):
if request.method == 'GET':
context = {
"T_Name": "My Name",
"T_Age": 50,
"T_Phone": 1478523699
}
return render(request, 'verifiedbysuperuser.html', context=context)
and a HTML template as follows,
<!DOCTYPE>
<html>
<body>
Name : {{ T_Name }}<br>
Age : {{ T_Age }}<br>
Phone : {{ T_Phone }}<br>
</body>
</html>
When you access your view, you will get a response like this,
In your case, you can pass as many attributes to template as dict (shown in my example) and in template/html keys of context (that is T_Name,T_Name etct) becomes variable. So you can directly use them in HTML inside the twin braces ({{ variable_name }})
As far as I knew, this is the general procedure for template rendering/ html rendering
UPDATE-1
def VerifiedBySuperuser(request):
if request.method == 'POST':
obj = MyModel.objects.get(id=some_id)
other_data = [1,2,3,4,] # some specific data
context = {
"post_data": request.data,
"object_instance": obj,
"some_other_data": other_data
}
return render(request, 'verifiedbysuperuser.html', context=context)

How do I scrape page content with a generator?

I have a blog where each post has a bunch of images and videos. I would like to be able to tag each of them with some keywords, and then populate a set of pages based on the tags. For example going to /photos/car/ would list all images tagged with car.
I include images and videos using a simple plugin right now, that essentially only has a render function. I figure I could add the tags there.
But how can I make Jekyll 'scrape' my pages and populate pages with images?
Short answer is : this is tricky.
But why ?
A custom imgWithTags-tag liquid tag like {% img cookie-monster.png tag2,tag3 %} can do two things :
render the html tag
store tag -> image associations in a site.taggedImage variable
As this tag can be used on any post, page or collection document, the site.taggedImage variable will only be complete after the render process.
Once the render process is finished, we can grab the :site, :post_render hook to process our datas and create Tags pages.
But here, we can no longer rely on things like {% for p in tagPages %}...{% endfor %} to automatically generate links to our pages : rendering is finished.
The trick can be to maintain a link data file by hand, in order to be able to generate links with loops like this {% for p in site.data.tagPages %}...{% endfor %}
Let's give it a try
NOTE : this works only with Jekyll version 3.1.x (not 3.0.x)
_plugins/imgWithTags-tag.rb
module Jekyll
class ImgWithTags < Liquid::Tag
# Custom liquid tag for images with tags
# syntax : {% img path/to/img.jpg coma, separated, tags %}
# tags are optionnal
#
# This plugin does two things :
# it renders html tag <a href='url'><img src='url' /></a>
# it stores tags -> images associations in site.config['images-tags']
Syntax = /^(?<image_src>[^\s]+\.[a-zA-Z0-9]{3,4})\s*(?<tags>[\s\S]+)?$/
def initialize(tag_name, markup, tokens)
super
if markup =~ Syntax then
#url = $1
#tags = $2.split(",").collect!{|tag| tag.strip } if !$2.nil?
else
raise "Image Tag can't read this tag. Try {% img path/to/img.jpg [coma, separated, tags] %}."
end
end
def render(context)
storeImgTags(context) if defined?(#tags) # store datas if we have tags
site = context.registers[:site]
imgTag = "<a href='#{ site.baseurl }/assets/#{#url}'><img src='#{ site.baseurl }/assets/#{#url}' /></a>"
end
def storeImgTags(context)
# store tagged images datas in site config under the key site.config['images-tags']
imagesTags = context.registers[:site].config['images-tags'] || {}
#tags.each{|tag|
slug = Utils.slugify(tag) # My tag -> my-tag
# create a tag.slug entry if it doesn't exist
imagesTags[slug] = imagesTags[slug] || {'name' => tag, 'images' => [] }
# add image url in the tag.images array if the url doesn't already exist
# this avoid duplicates
imagesTags[slug]['images'] |= [#url.to_s]
}
context.registers[:site].config['images-tags'] = imagesTags
end
end
end
Liquid::Template.register_tag('img', Jekyll::ImgWithTags)
At this point : all tagged images links are rendered and all tags->images associations are stored.
_plugins/hook-site-post-render-imagesTagsPagesGenerator.rb
Jekyll::Hooks.register :site, :post_render do |site, payload|
puts "++++++ site post_render hook : generating Images Tags pages"
imagesTags = site.config['images-tags'] # datas stored by img tag
linksDatas = site.data['imagesTagsLinks'] # tags pages link in data file
pagesFolder = 'tag'
imagesTags.each do |slug, datas|
tagName = datas['name']
tagImages = datas['images']
pageDir = File.join(pagesFolder, slug)
tagPage = Jekyll::ImageTagPage.new(site, site.source, pageDir, tagName, tagImages)
# as page rendering has already fired we do it again for our new pages
tagPage.output = Jekyll::Renderer.new(site, tagPage, payload).run
tagPage.trigger_hooks(:post_render)
site.pages << tagPage
# verbose check to see if we reference every tag url in out data file
if !linksDatas.key?(tagName) # check if tag is in imagesTagsLinks data file
puts "Warning ---------> #{tagName} not in data file"
puts "Add : #{tagName}: #{tagPage.url}"
puts "in data/imagesTagsLinks.yml"
puts
else
if tagPage.url != linksDatas[tagName] then # check if url is correct in imagesTagsLinks data file
puts "Warning ---------> incorrect url for '#{tagName}'"
puts "Replace : #{tagName}: #{linksDatas[tagName]}"
puts "by : #{tagName}: #{tagPage.url}"
puts "in data/imagesTagsLinks.yml"
puts
end
end
end
puts "++++++ END site post_render hook"
end
module Jekyll
class ImageTagPage < Page
def initialize(site, base, dir, tag, images)
#site = site
#base = base
#dir = dir
#name = 'index.html'
self.process(#name)
self.read_yaml(File.join(base, '_layouts'), 'tag_index.html')
self.data['tag'] = tag
self.data['images'] = images
self.data['title'] = "Images for tag : #{tag}"
end
end
end
And the Tag layout page
_layouts/tag_index.html
---
layout: default
---
<h2>{{ page.title }}</h2>
{% for i in page.images %}
<img src="{{ site.baseurl }}/assets/{{ i }}" alt="Image tagged {{ page.tag }}">
{% endfor %}
Here, everything is in place to generate tags page.
We can now do a jekyll build and see the verbose output just tell us what to add in _data/imagesTagsLinks.yml
_data/imagesTagsLinks.yml
tag1: /tag/tag1/
tag2: /tag/tag2/
...
We can now link to our tag page from everywhere with a simple
{% for t in site.data.imagesTagsLinks %}
<li>{{ t[0] }}</li>
{% endfor %}
I've told you : it's tricky. But It does the job.
Note: the img tag can be improved, and why not a figure tag ?

twig striptags and html special chars

I am using twig to render a view and I am using the striptags filter to remove html tags.
However, html special chars are now rendered as text as the whole element is surrounded by "".
How can I either strip special chars or render them, while still using the striptags function ?
Example :
{{ organization.content|striptags(" >")|truncate(200, '...') }}
or
{{ organization.content|striptags|truncate(200, '...') }}
Output:
"QUI SOMMES NOUS ? > NOS LOCAUXNOS LOCAUXDepuis 1995, Ce lieu chargé d’histoire et de tradition s’inscrit dans les valeurs"
If it could help someone else, here is my solution
{{ organization.content|striptags|convert_encoding('UTF-8', 'HTML-ENTITIES') }}
You can also add a trim filter to remove spaces before and after.
And then, you truncate or slice your organization.content
EDIT November 2017
If you want to keep the "\n" break lines combined with a truncate, you can do
{{ organization.content|striptags|truncate(140, true, '...')|raw|nl2br }}
I had a similar issue, this worked for me:
{{ variable |convert_encoding('UTF-8', 'HTML-ENTITIES') | raw }}
I was trying some of, among others, these answers:
{{ organization.content|striptags|truncate(200, true) }}
{{ organization.content|raw|striptags|truncate(200, true) }}
{{ organization.content|striptags|raw|truncate(200, true) }}
etc.
And still got strange characters in the final form. What helped me, is putting the raw filter on the end of all operations, i.e:
{{ organization.content|striptags|truncate(200, '...')|raw }}
Arf, I finally found it :
I am using a custom twig filter that just applies a php function:
<span>{{ organization.shortDescription ?: php('html_entity_decode',organization.content|striptags|truncate(200, '...')) }}</span>
Now it renders correctly
My php extension:
<?php
namespace AppBundle\Extension;
class phpExtension extends \Twig_Extension
{
public function getFunctions()
{
return array(
new \Twig_SimpleFunction('php', array($this, 'getPhp')),
);
}
public function getPhp($function, $variable)
{
return $function($variable);
}
public function getName()
{
return 'php_extension';
}
}
2022 update | tested with Drupal 8.6.16
I tried the top voted recommendation. It worked ok with some symbols but not with others.
raw filter seems to be working ok with all special characters.
like so
{{ organization.content|striptags|raw }}
The best way to do this is :
{{ organization.content|striptags|truncate(200, '...')|raw }}
With |raw always at the end.
Don't use convert_encoding('UTF-8', 'HTML-ENTITIES'), you will encounter iconv issues.
When I thought none of the above answers were working for me (convert_encoding running into iconv() issues in Drupal 9, and I thought raw, but because applying it on the argument side of an {% embed %} — as opposed to in the embedded template itself — didn't seem to help), another approach that seemed to work for me was:
{% autoescape false %}
{{ organization.content|striptags|truncate(200, '...') }}
{% endautoescape %}
with that false part being key.
I had the same problem, I resolved it byt this function below, using strip_tags.
<?php
namespace AppBundle\Extension;
class filterHtmlExtension extends \Twig_Extension
{
public function getFunctions()
{
return array(
new \Twig_SimpleFunction('stripHtmlTags', array($this, 'stripHtmlTags')),
);
}
public function stripHtmlTags($value)
{
$value_displayed = strip_tags($value);
return $value_displayed ;
}
public function getName()
{
return 'filter_html_extension';
}
}