Django remove leading zero - python

In a Django template how do I remove the first Zero from all the this mobile numbers I'm displaying. In Python I have tried this but with no success....
{% for object in data %}
{{ object.mobile.lstrip('0') }}
{% endfor %}
views.py
def sms(request, incentive):
objectQuerySet = Recipient.objects.filter(incentiveid=incentive)
context = {'data':objectQuerySet}
return render_to_response('smssend.html', context, context_instance=RequestContext(request))

There are many ways to do that.
write custom template filter
filter user input and store phones with leading zeros already stripped
create a custom object #property returning mobile with zeroes stripped (this one a little bit dirty)
do cleanup before rendering template

I assume you will need to use similar logic in other locations of your application so why not just add a method to your model to clean the data? The code below assumes your mobile field is a string.
class Recipient(models.Model):
...
def mobile_no_zero(self):
return self.mobile[1:] if self.mobile.startswith('0') else self.mobile
And then you can call the method from your template:
{% for object in data %}
{{ object.mobile_no_zero }}
{% endfor %}

You should pass your data to your template in the correct format. Django templates are not "Python interspersed with HTML" like PHP is.
For example, when you first pass your data in your view, you should make sure that it is an iterable with the zeroes already stripped.
There is no lstrip in the Django template mini-language.
Edit: If you know that the first digit will always be a 0, you can also do this:
{{ object|slice:"1:" }}

There is one method that does work (but is more of a kludge that anything and removes 0 or more 0s) - and only if the number can be converted to a float to start with (ie, no spaces)
In [23]: t = Template('{{ value|floatformat:0 }}')
In [24]: t.render(Context({'value': '00123'}))
Out[24]: u'123'

You can use cut ( it will cut all zeros from number )
or you can use
phone2numeric
Imo its beter opption

Related

How to disable escape for Django model field's value in template when rendering fields manually

I am working on one of my colleague's Django (Django 2.1.4) projects. I spent a couple of days to try to figure out how to disable auto escape for Form field's value when rendering it manually in a template. {% autoescape off %} and {{form1.LastName | safe }} all don't work.
Here are some relative codes.
Form.py
class tblstudentinfomodelform_page1(forms.ModelForm):
LastName = forms.CharField(max_length=30, required=True)
views.py
def application(request,application_num)
form1 = tblstudentinfo.objects.get(ApplicationNumber=application_num)
...
form1_forms = tblstudentinfomodelform_page1(initial=form1.__dict__) if form1 else tblstudentinfomodelform_page1(initial=form1)
...
return render(request,'appinfo.html',{'form1':form1_forms})
appinfo.html
<th>{{form1.LastName}}<br>{{form1.LastName.errors}} {{form1.LastName.value}} </th>
Some tests here:
LastName's value is Şhaha
test1: add {% autoescape off %} at the top of the template and {% endautoescape %} at the bottom
result1: {{form1.LastName.value}} displays correctly -- Şhaha, but input textbox shows Şhaha
run result -- html page
test2: delete autoescape tag and add safe filter
<th>{{form1.LastName | safe}}<br>{{form1.LastName.errors}} {{form1.LastName.value |safe}} </th>
result2: get the same result, looks like that safe filter only worked on form.field.value
Any suggestion?
Thank you.
Add the answer to here in case someone gets the same problem.
Create a function to unescape all HTML entities.
from html import unescape
def html_unescape(data_model): # convert to unicode characters
# Convert all named and numeric character references (e.g. >, >, >) in the string s to the corresponding Unicode characters.
for f in data_model._meta.get_fields():
if ( f.get_internal_type() == "CharField" or f.get_internal_type() == "TextField") and getattr(data_model, f.name):
#some old records haved escaped many times
str = unescape(unescape(unescape(unescape(unescape(getattr(data_model, f.name))))))
setattr(data_model, f.name, str)
return data_model
and then
form1 = tblstudentinfo.objects.get(ApplicationNumber=application_num)
form1 = html_unescape(form1)

Single View with Dynamic template

I've got modules that if enabled/disabled would require a different arrangement of tables and iframes on the frontend webpage. In order to do this I set up a function to check which modules are enabled/disabled and assigned a number to each 'set' and will be created separate templates for each "set1.html", "set2.html", "set3.html", etc...
I'd like to utilize one single view where I can pass the set number from from function I created but I can't seem to figure out how.
def homeset(request):
return render(request, 'app/set1.html', {})
Looking to figure out some way to make the "1" the return of the function I created to determine which set# to load as template and would prefer to not have to create a view for every single template needed.
Just taking a stab at this, do you have a problem with setting the template name before rendering?
def homeset(request):
# define 'my_set'
# define num
...
my_template_name = None
if num in my_set:
my_template_name = 'app/set{}.html'.format(num)
return render(request, my_template_name)
Looks like Scott Skiles answered your question, but an alternative way is to use a single base template and the "include" templatetag.
You can pass the set number to the template and use the "if" templatetag" to include the content from appropriate template(s) for each set number.
{% if set_num == 1 %}
{% include "foo/bar.html" %}
{% elif set_num == 2 %}
{% include "foo/two.html" %}
{% endif %}

In a jinja2 template, how do i check if an element in a mongo database is one of three possible strings?

My template has if/else functionality to handle displaying buttons on a page, I've managed to add an elif statement that displays the buttons only if an element in a mongo database is not one of three values. I'm trying to clean this up as the elif appears four times across two jinja2 templates. My code which works now looks like this:
{% elif (
('string1' not in database.category) and ('string2' not in database.category) and
('string3' not in database.category)) %}
I've tried declaring a tuple and doing a:
{% set hidebuttons = ['string1' , 'string2' , 'string3'] %} //sets tuple
{% elif not database.category in hidebuttons %} // checks if value not in tuple
and plenty of other methods to make this work but every time I reload the web page i keep seeing the buttons when i shouldn't be. Any advice is greatly appreciated.
I believe this should be in your view, not your template. If you need to do the query in more then one place, you can create a utility function that gets the results you need, then in your views, you can call the function and pass the data as context to your templates
if you're using a view_config decorator to render template, it could be something like:
#view_config(renderer='templates/foo.pt')
def my_view(request):
show_buttons = logic_to_determine_should_buttons_be_shown()
return {'show_buttons': show_buttons }
# your template
{% if show_buttons %}
show buttons
{% endif %}

How to pluralize a name in a template with jinja2?

If I have a template variable called num_countries, to pluralize with Django I could just write something like this:
countr{{ num_countries|pluralize:"y,ies" }}
Is there a way to do something like this with jinja2? (I do know this doesn't work in jinja2) What's the jinja2 alternative to this?
Thanks for any tip!
Guy Adini's reply is definitely the way to go, though I think (or maybe I misused it) it is not exactly the same as pluralize filter in Django.
Hence this was my implementation (using decorator to register)
#app.template_filter('pluralize')
def pluralize(number, singular = '', plural = 's'):
if number == 1:
return singular
else:
return plural
This way, it is used exactly the same way (well, with parameters being passed in a slightly different way):
countr{{ num_countries|pluralize:("y","ies") }}
Current Jinja versions have the i18n extension which adds decent translation and pluralization tags:
{% trans count=list|length %}
There is {{ count }} {{ name }} object.
{% pluralize %}
There are {{ count }} {{ name }} objects.
{% endtrans %}
You can use this even if you don't actually have multiple language versions - and if you ever add other languages you'll have a decent base which requires no changes (not all languages pluralize by adding an 's' and some even have multiple plural forms).
According to Jinja's documentation, there is no built in filter which does what you want. You can easily design a custom filter to do that, however:
def my_plural(str, end_ptr = None, rep_ptr = ""):
if end_ptr and str.endswith(end_ptr):
return str[:-1*len(end_ptr)]+rep_ptr
else:
return str+'s'
and then register it in your environment:
environment.filters['myplural'] = my_plural
You can now use my_plural as a Jinja template.
You also want to check if the word is already plural. Here is my solution:
def pluralize(text):
if text[-1:] !='s':
return text+'s'
else:
return text
Then register the tag to your environment (this can be applied to the Django templating engine too).

Django History for Custom Dashboard

I have decided to use Django-Simple-History for building a history of my models. In turn using that to build the dashboard. I have run into a bit of a snag though. I'm trying to output [User] [added,changed, deleted] [object] on/at [time] but I can't figure it out for the life of me.
So far I am able to display the historical record on the template but I can't access anything else, am I missing something?
I was hoping someone with knowledge of Simple History can help, since I couldn't get a hold of the author.
Here is the code snippets I have so far.
Models.py
from simple_history.models import HistoricalRecords
class Project(django.db.models.Model):
...
history = HistoricalRecords()
Views.py
#login_required
def addTMProject(request):
user = request.user
if request.method == 'POST':
form = TimeMaterialsForm(request.POST)
if form.is_valid():
project = form.save(commit=False)
project.created_by = request.user
today = datetime.date.today()
project.pre_quote = "%s-" % (str(today.year)[2:4])
project.quote = Project.objects.latest().quote+1
project.save()
project.history.all()
...
And I have also passed it on my dashboard/views.py so I have access to it.
#login_required
def view_dash(request):
today = datetime.date.today()
user = request.user
proj_perm = user.has_perm('project.add_project')
project = Project.objects.all().order_by('-proj_name')
query = Project.objects.all().order_by('-id')[:5]
que_quotes = Project.objects.filter(status__value__exact = 'Quote')
expired = FollowUp.objects.filter(next_followup__lte=today).order_by('next_followup').filter(archived=False)
log = LogEntry.objects.select_related().all().order_by("-id")
hist = Project.history.all()
return render_to_response('dashboard/home.html', {'user': user, 'project': project, 'query':query, 'que_quotes':que_quotes, 'expired':expired,
'proj_perm':proj_perm, 'log': log, 'hist':hist,}, context_instance=RequestContext(request))
And finally a snippet from my template. As it is right now, the {{ h }} shows "Testing Simple Records as of 2011-04-29 10:43:57" on the template
home.html
{% if user.is_authenticated %}
<div id="large_box">
<h5>Activity</h5>
{% for h in hist %}
<ul>
<li>{{ h }}</li>
</ul>
{% endfor %}
If anyone could help or point me to some more in depth documentation, then that would be great!
Thanks everyone!
Django-Simple-History simply creates a model (and associated database table) that mirrors the object you tie it to and adds four additional fields: history_id, history_date, history_type, and history_object.
history_id: standard primary key
history_date: datetime for when the change occurred
history_type: one of +, ~, -. (+ means added, ~ means changed, and - means deleted)
history_object: representation of the model that history is being stored for
So, at most basic level, you can roughly get "[added,changed, deleted] [object] on/at [time]" in your output, using something to the effect of:
{{ h.history_type }} {{ h.history_object }} on/at {{ h.history_date }}
You'll probably want to create template tag or something to convert the +, ~, and - to the more understandable, 'Created', 'Changed', 'Deleted'. {{ h.history_object }} should return the object's __unicode__, I'm assuming, so you might need to make some modifications there or return something like {{ h.history_object.__class__ }} or {{ h.history_object._meta.verbose_name }}, instead. (Not sure if those will actually work in practice though.) And, of course, you can apply the date filter to {{ h.history_date }} to make it any format you want.
Getting the user is more difficult. Django-Simple-History doesn't seem to store this data, so there's no record of what user made the modification. However, since it basically duplicates the object as it existed, you could probably get away with adding a modified_by field to your model and filling that with request.user pre-save. Then, when Django-Simple-History does its thing, that field would be copied over like the rest and be available via {{ h.modified_by }}.
I'm assuming that the only problem you're having is with the displaying of the historical data and not the actual saving portion of it.
I'm not sure what fields you have in your Project model, but it looks like the history field is treated like a foreign key field. This foreign key's table contains the same fields that your Project model does. So, if you want to access the fields you'd have to do something like this in your template:
...
{% for h in hist %}
<ul>
<li>{{h.field1}} {{h.field2}} {{h.field3}} on {{h.field4}}</li>
</ul>
{% endfor %}
...
I found this page (http://qr7.com/2010/10/django-simple-history-ftw/) which was quite helpful, but you'll have to play around with the history field names. I wasn't quite sure what they actually were.
Hope that helps.

Categories

Resources