How can I use Django intcomma in integerfield - python

I'd like to separate numerical values in the form with a comma in my Django project.
Then I found the documentation below:
https://docs.djangoproject.com/en/2.0/ref/contrib/humanize/
I thought that I can use 'intcomma' for my purpose. So I added "django.contrib.humanize" to my INSTALLED_APPS setting. And put {% load humanize %} in a template.
When I use 'intcomma' like below, it worked.
{{ 999999|intcomma }} # 999,999
But It did not work for integer form like below:
{{ form.numbers|intcomma }} # did not work.
A code was displayed to html instead of numbers like this:
<input type="number" name="int_sample" value="100000" id="id_int_sample"
My Django version is 2.0.1.

Formatting the value of an IntegerField
You access the value of an IntegerField with the .value attribute, so:
{{ form.numbers.value|intcomma }}
Note that this is the value set to the Form when you construct it. For example through initial={..} or the value that corresponds to the instance=... you pass to the field. If you for example in th form change the value, the content will not change.
Generating an <input> with number formatting
In case we want the <input> element itself to format the number separated with comma's, we will need some HTML/JavaScript. Since Django basically only renders a webpage. How the webpage behaves in the browser is not really the responsibility of Django.
We can for example use the following approach:
<script language="JavaScript">
function commas(input){
input.value = Number(input.value).toLocaleString();
}
</script>
{{ form.numbers }}
And the Form should then make sure the commas function is invoked:
SomeForm(forms.Form):
numbers = forms.IntegerField(
widget=forms.TextInput(attrs={'onclick':'commas(self)'})
)

Related

How do I obfuscate data in variables in jinja2? e.g. variable = "John Smith", I want something like "Odsv Wgtvs"

So I am trying to create a page where details are only shown to users who are logged in. I am able to change the content statically using
{% if user.is_authenticated %}
So I can replace something like {{ celebrity.name }} with Dummy Name, but then every occurrence of this is the same.
I'm hoping there is an easy way to mess with celebrity.name to obfuscate the actual data.
If there is no easy way I'll happily write my own function, but at this point I'm not sure if I should be writing it in jinja2 in the html template or if I should do it in views.py so would appreciate some guidance.
You could write your own custom template filter:
from django import template
register = template.Library()
#register.filter
def obfuscate(value, user):
if user.is_authenticated():
return value
# do something before returning
return '#SECRET#' + value + '#SECRET#'
This could be user in the template:
{{ celebrity.name|obfuscate:user }}
If the obfuscation has to be deterministic (same values always yield the same obfuscated result) you could use a hash function (will return giberrish, not real names), or a fixed dictionary which you use to subsitute names, or something else.
If the replacement can be non-deterministic, you could use some random char replacements.
Use set
{% if user.is_authenticated %}
{% set celebrity_name = celebrity.name %}
{% else %}
{% set celebrity_name = "dummy" %}
Or do you want to have unique dummy values..? You could assign anything from Python to celebrity_name if you want to use different values.

How can I include a "* required field." message in all forms with required fields?

I'm using django-crispy-forms with CRISPY_TEMPLATE_PACK = 'bootstrap3'. My templates looks like this (this is an example of the sign up form, but I have a lot of forms in my templates):
{% load crispy_forms_tags %}
<h1>Sign up</h1>
<form action="/accounts/signup/" method="POST" role="form">
{% csrf_token %}
{{ form|crispy }}
<button type="submit" class="btn btn-primary">Sing up</button>
</form>
In the rendered pages, the required fields appear correctly with an * near it to indicate that they are required, but no message appears explaining what an * means.
In my case, I'm dealing with users that are sometimes not very tech-firendly, so they might not know what an * means. I would like to show a * required field. message in the top of all forms with required fields.
I could put a <p>* required field.</p> line in the beginning of each form, but I would like to know if there is a more elegant and DRY way to do it.
Thank you!
You can override the uni_form.html template with a custom one.
https://github.com/maraujop/django-crispy-forms/blob/dev/crispy_forms/templates/bootstrap3/uni_form.html
According to the django crispy forms documentation:
https://django-crispy-forms.readthedocs.org/en/latest/crispy_tag_forms.html#change-required-fields
You will need to override the field template, that is your only option, unless you use a css hack (maybe something :before and :after for the asterisk element).
Your other option is to use the HTML crispy forms element, to make a notice at the top of your form:
HTML('<strong>Fields marked with * are required</strong>')
One solution would be to either add <p class="req_legend" style="display: none;">* required field.</p> to every form and add a js which changes its display property if required fields are found.
Here is a jquery example:
$(document).ready(function() {
if ($('.requiredField').length > 0) {
$('p.req_legend').show();
}
});
Or go full javascript and add <p> element to your only if you find a requiredField, you can than do this in a javascript that you add to the Media class of your forms

How to escape {{ or }} in django template?

Django treats {{ var }} as some variable in its template. How can I escape {{ var }} or {{ or }} such that django does not treat it as variable.
<p>"{{ some text }}"</p> Should prints exactly the same.
Django 1.5 introduced {% verbatim %} template tag. It stops template from parsing contents of this tag:
{% verbatim %}
{{ var }}
{% endverbatim %}
will be rendered as:
{{ var }}
I believe you are looking for the templatetag template tag.
As the linked-to doc states,
Since the template system has no concept of "escaping", to display one of the bits used in template tags, you must use the {% templatetag %} tag.
For example:
<p>"{% templatetag openvariable %} some text {% templatetag closevariable %}"</p>
will appear as so:
<p>"{{ some text }}"</p>
Edit: I don't really recommended this because it's not very clean, but it's still an option.
I was searching for one that I could use with JQuery Templates and figured a way to do it without tags or filters. This is as short as I could get it:
{{ "{{ any text }" }}}
Is printed as:
{{ any text }}
Why it works? Any text within {{}} is displayed as is, as long as it doesn't have two closing braces }} in a row. Then there are three brackets in a row, django interprets two first ones as end of the variable leaving one additional closing brace.
You can try escaping with html character escapes like:
{ = {
} = }
<p>"{{ some text }}"</p>
Update
In case anyone is trying to use the actual tags for javascript, verbatim is a better solution:
Stops the template engine from rendering the contents of this block tag.
{% verbatim %}
{{if dying}}Still alive.{{/if}}
{% endverbatim %}
if you simply need to use {{ }} as a variable for template framework like angularjs, then following maybe simpler:
in your <app path>/templatetags/ngvar.py , add
from django import template
register = template.Library()
#register.simple_tag
def ngvar(var_name):
return "{{%s}}" % var_name
and in template, do
{% load ngvar %}
{% ngvar "variable name" %}
if ngvar.py is the first template tag, then make sure to add __init__.py file to the templatetags directory
Another option would be to add a word joiner (zero width no-break space) between each curly bracket:
<p>"{⁠{ some text }⁠}"</p>
Although the above answers can solve the original problem, I add some hack around here for those who are scratching their heads like me.
Some times, we want to render a single brace followed by a variable. For example, in BibTeX, there may be something look like this:
#MISC{hu2012-spectral,
author = {Hu, Pili},
title = {Spectral Clustering Survey},
howpublished = {GitHub, https://github.com/hupili/tutorial/tree/master/spectral-clustering},
month = {May},
year = {2012}
}
Those bib fields come from template variables. If you write
title = {{{title}}},
jinja can not compile and raise an error. If you write
title = { {{title}} },
there will be extra blanks. The hack around is to store '{' and '}' as variables and use later.
{% set lb = '{' %}
{% set rb = '}' %}
...
#MISC{{lb}}{{ meta.bib_key }},
author = {{lb}}Hu, Pili{{rb}},
title = {{lb}}{{ meta.title }}{{rb}},
howpublished = {{lb}}GitHub, https://github.com/hupili/tutorial/tree/master/{{ auto.path}}{{rb}},
month = {{lb}}{{ meta.month }}{{rb}},
year = {{lb}}{{ meta.year }}{{rb}}
}
This looks clumsy but it is the best I find so far. If you have a cleaner solution, please tell me.
This template tag (designed for use with jQuery Templates) might do the trick. It let's you wrap content you don't want Django to interpret as variables with a template tag.
it can be solved by avoing adjacent angular backets, if its inside javascript code then you can write
'{'+'{address.'+key+'}}'
I used this to print jinja variables into another template,using javascript.
Jinja, which is what is being used for the templates, offers several suggestions for escaping here. What has worked best for me is using something like "{% raw %}{{ some text }}{% endraw %}"

Python / Django Forms - Display Form Element Content Instead of Html Element

I am looping through some forms and I want to display some of the values of certain form elements. I have read that .data should take care of this for me. However, that returns "None" and the form does indeed have the field and correct stored value...
{% for document in documents: %}
{{ document.title.data }} <!-- NOTE: This returns "None" -->
{{ document.title }} <!-- Element with correct initial value -->
Any ideas?
Merci Beaucoup!!!
Update:
To access an initial value directly forms.CharField(initial=X)
Use {{ document.title.field.initial }}.
Accessing an initial value passed into the form constructor (form = MyForm(initial={...})) doesn't look possible via the template. BoundField does data = self.form.initial.get(self.name, self.field.initial) when rendering a widget to get at the form initial dict, then falls back to the form field's initial value.
For a bound form where you've passed in data, such as form = MyForm(request.POST),
that data would be available in
{{ document.title.data }}
In trunk, BoundField.value returns either the initial or data! Cool stuff.
http://code.djangoproject.com/browser/django/trunk/django/forms/forms.py#L438

How do I create a Django form that displays a checkbox label to the right of the checkbox?

When I define a Django form class similar to this:
def class MyForm(forms.Form):
check = forms.BooleanField(required=True, label="Check this")
It expands to HTML that looks like this:
<form action="." id="form" method=POST>
<p><label for="check">Check this:</label> <input type="checkbox" name="check" id="check" /></p>
<p><input type=submit value="Submit"></p>
</form>
I would like the checkbox input element to have a label that follows the checkbox, not the other way around. Is there a way to convince Django to do that?
[Edit]
Thanks for the answer from Jonas - still, while it fixes the issue I asked about (checkbox labels are rendered to the right of the checkbox) it introduces a new problem (all widget labels are rendered to the right of their widgets...)
I'd like to avoid overriding _html_output() since it's obviously not designed for it. The design I would come up with would be to implement a field html output method in the Field classes, override the one for the Boolean field and use that method in _html_output(). Sadly, the Django developers chose to go a different way, and I would like to work within the existing framework as much as possible.
CSS sounds like a decent approach, except that I don't know enough CSS to pull this off or even to decide whether I like this approach or not. Besides, I prefer markup that still resembles the final output, at least in rendering order.
Furthermore, since it can be reasonable to have more than one style sheet for any particular markup, doing this in CSS could mean having to do it multiple times for multiple styles, which pretty much makes CSS the wrong answer.
[Edit]
Seems like I'm answering my own question below. If anyone has a better idea how to do this, don't be shy.
Here's a solution I've come up with (Django v1.1):
{% load myfilters %}
[...]
{% for field in form %}
[...]
{% if field.field.widget|is_checkbox %}
{{ field }}{{ field.label_tag }}
{% else %}
{{ field.label_tag }}{{ field }}
{% endif %}
[...]
{% endfor %}
You'll need to create a custom template tag (in this example in a "myfilters.py" file) containing something like this:
from django import template
from django.forms.fields import CheckboxInput
register = template.Library()
#register.filter(name='is_checkbox')
def is_checkbox(value):
return isinstance(value, CheckboxInput)
More info on custom template tags available here.
Edit: in the spirit of asker's own answer:
Advantages:
No futzing with CSS.
The markup ends up looking the way it's supposed to.
I didn't hack Django internals. (but had to look at quite a bunch)
The template is nice, compact and idiomatic.
The filter code plays nice regardless of the exact values of the labels and input field names.
Disadvantages:
There's probably something somewhere out there that does it better and faster.
Unlikely that the client will be willing to pay for all the time spent on this just to move the label to the right...
I took the answer from romkyns and made it a little more general
def field_type(field, ftype):
try:
t = field.field.widget.__class__.__name__
return t.lower() == ftype
except:
pass
return False
This way you can check the widget type directly with a string
{% if field|field_type:'checkboxinput' %}
<label>{{ field }} {{ field.label }}</label>
{% else %}
<label> {{ field.label }} </label> {{ field }}
{% endif %}
All presented solutions involve template modifications, which are in general rather inefficient concerning performance. Here's a custom widget that does the job:
from django import forms
from django.forms.fields import BooleanField
from django.forms.util import flatatt
from django.utils.encoding import force_text
from django.utils.html import format_html
from django.utils.translation import ugettext as _
class PrettyCheckboxWidget(forms.widgets.CheckboxInput):
def render(self, name, value, attrs=None):
final_attrs = self.build_attrs(attrs, type='checkbox', name=name)
if self.check_test(value):
final_attrs['checked'] = 'checked'
if not (value is True or value is False or value is None or value == ''):
final_attrs['value'] = force_text(value)
if 'prettycheckbox-label' in final_attrs:
label = _(final_attrs.pop('prettycheckbox-label'))
else:
label = ''
return format_html('<label for="{0}"><input{1} /> {2}</label>', attrs['id'], flatatt(final_attrs), label)
class PrettyCheckboxField(BooleanField):
widget = PrettyCheckboxWidget
def __init__(self, *args, **kwargs):
if kwargs['label']:
kwargs['widget'].attrs['prettycheckbox-label'] = kwargs['label']
kwargs['label'] = ''
super(PrettyCheckboxField, self).__init__(*args, **kwargs)
# usage in form
class MyForm(forms.Form):
my_boolean = PrettyCheckboxField(label=_('Some label'), widget=PrettyCheckboxWidget())
I have PrettyCheckboxWidget and PrettyCheckboxField in an extra file, so they may be imported where needed. If you don't need translations, you can remove the ugettext parts. This code works on Django 1.5 and is untested for lower versions.
Advantages:
Highly performant, needs no template modifications
Easy to use as a custom widget
Disadvantages:
"as_table" renders the checkbox + label inside the second column
{{ field.label }} inside the template is empty. The label is instead bound to {{ field }}
More work than I planned on doing on a Saturday ;-)
I know that the user excluded CSS, but considering the top answers take about half hour of work to do such a small thing, but knowing that details like these are important on a website, I'd settle for the CSS solution.
checkbox.css
input[type="checkbox"] {
float: left;
margin-right: 10px;
margin-top: 4px;
}
forms.py
class MyForm(forms.ModelForm):
# ...
class Media:
css = {
'all': 'checkbox.css',
}
template.html
{{ form.media }}
{{ form.as_p }}
Advantages:
fast!
no futzing with template tags (just form.as_p)
no new damned widgets
the CSS file is automatically included in every form
Disadvantages:
the HTML doesn't reflect the presentation (but is good enough!)
your frontendist could complain
Here's what I ended up doing. I wrote a custom template stringfilter to switch the tags around. Now, my template code looks like this:
{% load pretty_forms %}
<form action="." method="POST">
{{ form.as_p|pretty_checkbox }}
<p><input type="submit" value="Submit"></p>
</form>
The only difference from a plain Django template is the addition of the {% load %} template tag and the pretty_checkbox filter.
Here's a functional but ugly implementation of pretty_checkbox - this code doesn't have any error handling, it assumes that the Django generated attributes are formatted in a very specific way, and it would be a bad idea to use anything like this in your code:
from django import template
from django.template.defaultfilters import stringfilter
import logging
register=template.Library()
#register.filter(name='pretty_checkbox')
#stringfilter
def pretty_checkbox(value):
# Iterate over the HTML fragment, extract <label> and <input> tags, and
# switch the order of the pairs where the input type is "checkbox".
scratch = value
output = ''
try:
while True:
ls = scratch.find('<label')
if ls > -1:
le = scratch.find('</label>')
ins = scratch.find('<input')
ine = scratch.find('/>', ins)
# Check whether we're dealing with a checkbox:
if scratch[ins:ine+2].find(' type="checkbox" ')>-1:
# Switch the tags
output += scratch[:ls]
output += scratch[ins:ine+2]
output += scratch[ls:le-1]+scratch[le:le+8]
else:
output += scratch[:ine+2]
scratch = scratch[ine+2:]
else:
output += scratch
break
except:
logging.error("pretty_checkbox caught an exception")
return output
pretty_checkbox scans its string argument, finds pairs of <label> and <input> tags, and switches them around if the <input> tag's type is "checkbox". It also strips the last character of the label, which happens to be the ':' character.
Advantages:
No futzing with CSS.
The markup ends up looking the way it's supposed to.
I didn't hack Django internals.
The template is nice, compact and idiomatic.
Disadvantages:
The filter code needs to be tested for exciting values of the labels and input field names.
There's probably something somewhere out there that does it better and faster.
More work than I planned on doing on a Saturday.
Changing checkbox position in Django admin can be quite tricky, but luckily there is a simple solution using custom widget:
from django.forms.widgets import Widget, CheckboxInput, boolean_check
class RightCheckbox(Widget):
render = CheckboxInput().render
def __init__(self, attrs=None, check_test=None):
super(RightCheckbox, self).__init__(attrs)
self.check_test = boolean_check if check_test is None else check_test
Django uses left position only when widget is subclass of CheckboxInput
Order of inputs and labels is provided via normal_row parameter of the form and there are no different row patterns for checkboxes. So there are two ways to do this (in 0.96 version exactly):
1. override _html_output of the form
2. use CSS to change position of the label and checkbox

Categories

Resources