text slicing not working - django

template.html
{{list.report.description|default:"No description available"|slice:"45" }}{% if list.report.description|length > 45 %}...{% endif %}
1.This is slicing if character entered more than 45.
2.It produce problem while creating new report,if no description is given,it should display the default text as "No description available" but instead it is displaying the text along with 3 dots.
2.No problem if the field is saved with empty,it is displaying default as "No description available".
Thanks

Although I am not entirely sure why your code isn't working, it's the "wrong" thing to do anyhow.
Try the truncatechars method instead: https://docs.djangoproject.com/en/dev/ref/templates/builtins/#truncatechars
{{ value|truncatechars:9 }}
If value is Joel is a slug, the output will be Joel i....
For Django 1.3 or older, use the following templatetag: http://djangosnippets.org/snippets/444/
from django import template
register = template.Library()
#register.filter
def truncatechars(s, num):
"""
Truncates a word after a given number of chars
Argument: Number of chars to truncate after
"""
length = int(num)
string = []
for word in s.split():
if len(word) > length:
string.append(word[:length]+'...')
else:
string.append(word)
return u' '.join(string)

Related

How to translate numbers in django translation?

My head could not click how to translate numbers in django translation. It is not possible to translate by string id. I could print 2020 like:
{% translate '2' %}{% translate '0' %}{% translate '2' %}{% translate '0' %}
Obvioulsy, It is not the way. So, I am missing something. I would want something like:
{% translate "2020"|number %} # May be ?? It should be that easy right?
It should be that, translation from 0 to 9.
Django doesn't have this functionality (yet), but you can achieve the same by creating a custom template tag. You can read the whole documentation of creating the tag here, Custom template tags and filters.
By this way, you can translate Arabic Numerals (or anything) to any form, all you need is a mapper dict and a function that converts things by using the mapper dict.
We need to have a dict that has the source numerals as keys and target numeral as values. In this case, I assume you need to translate from Arabic numerals to nepali numerals
So, I have created a simple mapper using dict and converted the receiving value to something else using the translate_nepal_numeral(...) function.
from django import template
from django.template.defaultfilters import stringfilter
NUMBER_MAP = {
"0": "०",
"1": "१",
"2": "२",
# and so on
}
register = template.Library()
#register.filter()
#stringfilter
def translate_nepal_numeral(value):
try:
return "".join([NUMBER_MAP[char] for char in value])
except KeyError:
return value
Then in your template,
{% load custom_numerals %}
{{ "2010"|translate_nepal_numeral }}
Examples
In [3]: translate_nepal_numeral("2020")
Out[3]: '२०२०'
In [4]: translate_nepal_numeral("2120")
Out[4]: '२१२०'
In [5]: translate_nepal_numeral("2120a")
Out[5]: '2120a'
Notes
If you are passing a non-numeral, this function will return the input

How to use linebreak in Django templates

Hi I am new to python Django.
I want new line in specific places, So I tried
def abc(request):
text = "This is\n a good example"
return render(request, 'test.html', {'text' : text})
In HTML part
Hello {{ text|linebreaks }}
And this is working perfectly fine with output
Hello This is
a good example
Here is my question
I store some 400 - 800 words in my database which has approximately 4-5 paragraph.
I want to new line here.
So, I store data like "This is\n a good example" in my database.
And simply call it in django template(Html side)
but it prints
Hello This is\n a good example
In here why line break is not working?
My HTML true code
{% for essay in eassays %}
{{ essay.description|linebreaks }}
{% endfor %}
I have changed name. Also, I am loading 100 such data.
Any possible solution or other logic!
Thankyou!
So, I store data like "This is\n a good example" in my database.
You likely stored '\\n' in the database, so a backslash, followed by an n. Not a new line chacter '\n' [wiki]. Note that if you write \n in a form element, then it will be escaped and thus stored accordingly.
It might be better to use a <textarea> in your form elements to let users use new lines (by pressing Enter).
You can try to fix the damage by substituting the strings, with:
from django.db.models import Replace, Value
Essay.objects.update(
description=Replace('description', Value('\\n'), Value('\n'))
)
and thus update your database such that '\\n' is now replaced by '\n'.

Custom template filter: replace HTML element with regex filtered text (Django 2.1)

I am building a search engine, which needs a custom filter that displays the text surrounding a keyword, like the excerpts on Google results page. I am using regex to identify the surrounding words. Here is my code for the filter:
#register.filter(needs_autoescape=True)
#stringfilter
def show_excerpt (value, search_term, autoescape=True):
# make the keyword put into the search engine case insensitive #
keywords = re.compile(re.escape(search_term), re.IGNORECASE)
# make excerpt return 300 characters before and after keyword #
excerpt_text = '.{300}' + str(keywords) + '.{300}'
# replace the original text with excerpt #
excerpt = value.sub(excerpt_text, value)
return mark_safe(excerpt)
Code for the search engine in view.py:
def query_search(request):
articles = cross_currents.objects.all()
search_term = ''
if 'keyword' in request.GET:
search_term = request.GET['keyword']
articles = articles.annotate(similarity=Greatest(TrigramSimilarity('Title', search_term), TrigramSimilarity('Content', search_term))).filter(similarity__gte=0.03).order_by('-similarity')
context = {'articles': articles, 'search_term': search_term}
return render(request, 'query_search.html', context)
HTML template (it includes a custom highlight filter that highlights the keyword put into search engine):
<ul>
{% for article in articles %}
<li>{{ article|highlight:search_term }}</li>
<p> {{ article.Content|highlight:search_term|show_excerpt:search_term }} </p>
{% endfor %}
</ul>
Error message: 'SafeText' object has no attribute 'sub'
I think I am doing .sub wrong. I just need the excerpt to replace the entire original text (the text that I am putting a filter on). The original text starts from the beginning of the data but I just want to display the data surrounding the keyword, with my highlight custom filter highlighting the keyword (just like on Google). Any idea?
EDIT: when I do re.sub(excerpt_text, value), I get the error message sub() missing 1 required positional argument: 'string'.
You need to call re.sub(), not value.sub(). You are calling sub on a SafeText object, .sub() is a regex function.
I haven't tested your code but if the remaining code is correct you should just change that line to re.sub(excerpt_text, value)
I decided to ditch regex and just do good old string slicing. Working code for the filter:
#register.filter(needs_autoescape=True)
#stringfilter
def show_excerpt(value, search_term, autoescape=True):
#make data into string and lower#
original_text = str(value)
lower_original_text = original_text.lower()
#make keyword into string and lower#
keyword_string = str(search_term)
lower_keyword_string = keyword_string.lower()
#find the position of the keyword in the data#
keyword_index = lower_original_text.find(lower_keyword_string)
#Specify the begining and ending positions of the excerpt#
start_index = keyword_index - 10
end_index = keyword_index + 300
#Define the position range of excerpt#
excerpt = original_text[start_index:end_index]
return mark_safe(excerpt)

How to interpolate already translated string in Django templates?

I have a generic delete view that includes a confirmation question as a translated string containing one placeholder. I would like to interpolate it like this:
<p class="text-error">
{% message % object %}
</p>
Variable message contains a string like: "Do you want to remove user %s?".
How can I use string interpolation in templates?
You can use the following dictionary with strings:
strings = { 'object': 'word' }
as follows:
{{ strings|stringformat:message }}
with the stringformat filter. Note that the leading % is dropped from the string (see the documentation for more details).
Finally I made a custom filter:
from django.template.base import Library
register = Library()
#register.filter
def interpolate(value, arg):
"""
Interpolates value with argument
"""
try:
return value % arg
except:
return ''

Make the first letter uppercase inside a django template

I am pulling a name from a database which is stored as myname. How do I display this inside a Django template as Myname, with the first letter being in uppercase.
Using Django built-in template filter called title
{{ "myname"|title }}
I know it's a bit late, but you can use capfirst:
{{ "waiting for action"|capfirst }}
This will result into "Waiting for action"
This solution also works if you have multiple words (for example all caps):
{{ "ALL CAPS SENTENCE"|lower|capfirst }}
This will output "All caps sentence".
The title filter works fine, but if you have a many-words string like: "some random text", the result is going to be "Some Random Text". If what you really want is to uppercase only the first letter of the whole string, you should create your own custom filter.
You could create a filter like this (follow the instructions on how to create a custom template filter from this doc - it's quite simple):
# yourapp/templatetags/my_filters.py
from django import template
register = template.Library()
#register.filter()
def upfirstletter(value):
first = value[0] if len(value) > 0 else ''
remaining = value[1:] if len(value) > 1 else ''
return first.upper() + remaining
Then, you should load the my_filters file at your template, and use the filter defined there:
{% load my_filters %}
...
{{ myname|upfirstletter }}
It worked for me in template variable.
{{ user.username|title }}
If the user is "al hasib" then the it will return "Al Hasib"
or
{{ user.username|capfirst }}
If user is 'hasib' then the last one will return "Hasib"
Both look something like same but there's some differences.
use
{{"myname"|title}}
this will make the fist letter of each word capital
Just use {{myname | capfirst}}
In Django the template filter capfirst capatialize the first letter of a given string.