Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make a form field numeric only in Django

While using Django modelforms I have a Integer field which is numeric only. But in the browser it comes as a text field in which I can enter "characters". I want to make this only "numeric". How to do this ? i.e. users should be able to enter only numbers.

We can do it 1 way by setting the attribute of the field.

1)

def __init__(self,*args,**kwargs):

        super(PropertyForm,self).__init__(*args, **kwargs)        
        self.fields['brokers_phone_number'].widget.attrs['type'] = "number"

This does not seem to work. I am using html 5 and the browser is Chrome. What am I doing wrong ? How can It be done better ?

like image 706
Akash Deshpande Avatar asked Sep 26 '13 07:09

Akash Deshpande


People also ask

How do you exclude a specific field from a ModelForm?

Set the exclude attribute of the ModelForm 's inner Meta class to a list of fields to be excluded from the form.

How do you customize a form in Django?

So, we have to just design the HTML with css, and use it in Django by just replacing the input tag with render_field and form. field_name with {% %} at the end and design it with our choice.

How do I make a field optional in Django?

You would have to add blank=True as well in field definition. If the model field has blank=True, then required is set to False on the form field. Otherwise, required=True. Don't forget to reset and sync DB again after changing this.


5 Answers

Django 1.6 has a NumberInput Widget, but 1.6 is currently not stable.

But you could try something like this:

from django.forms import ModelForm, CharField, TextInput

class PropertyForm(ModelForm):

    brokers_phone_number = CharField( widget=TextInput(attrs={'type':'number'}))

    class Meta:
     ...
like image 74
shry Avatar answered Oct 07 '22 15:10

shry


In the end I ended up using a jQuery based solution. Question here. Instead of adding type I added a class "number" and added jquery number validation on it. But this is a hackish solution, especially when we have html 5 "number" in place. If anyone finds a way to do this please answer.

In the form:

 def __init__(self,*args,**kwargs):
    super( PropertyFloorForm, self).__init__(*args, **kwargs)
    self.fields['number_of_units'].widget.attrs['class'] = "number"

In the template

$(document).ready(function() {
    $(".number").keydown(function(event) {
        // Allow: backspace, delete, tab, escape, and enter
        if (event.keyCode == 46 || event.keyCode == 8 || event.keyCode == 9 || event.keyCode == 27 || event.keyCode == 13 ||
            // Allow: Ctrl+A
            (event.keyCode == 65 && event.ctrlKey === true) ||
            // Allow: home, end, left, right
            (event.keyCode >= 35 && event.keyCode <= 39)) {
            // let it happen, don't do anything
            return;
        } else {
            // Ensure that it is a number and stop the keypress
            if (event.shiftKey || (event.keyCode < 48 || event.keyCode > 57) && (event.keyCode < 96 || event.keyCode > 105)) {
                event.preventDefault();
            }
        }
    });
});
like image 37
Akash Deshpande Avatar answered Oct 07 '22 17:10

Akash Deshpande


Here is another solution:

  • Add validators in the model file
  • Add css class to fields in the model form
  • Use jquery to change type of the the above class to 'number' on document/page load

IN THE MODEL:

    exp_from = models.IntegerField(default=0,
        validators=[
            MaxValueValidator(100),
            MinValueValidator(0)
        ])

    exp_to = models.IntegerField(default=1,
        validators=[
            MaxValueValidator(100),
            MinValueValidator(1)
        ])

IN THE MODEL FORM - add a jquery class

self.fields['exp_from'].widget.attrs['class'] = "text_type_number"
self.fields['exp_to'].widget.attrs['class'] = "text_type_number"

IN THE HTML FILE/JS FILE

$(document).ready(function(){
   $('.text_type_number').attr('type', 'number');
});
like image 21
Nav Avatar answered Oct 07 '22 15:10

Nav


I know this is a faily old thread, am adding this for posterity

To get around this issue save the following as html5type.py

from django import template
register = template.Library()
def html5type(var):
    if isinstance(var, int):
        return 'number'
    else:
        return 'text'  

register.filter('html5type', html5type)

Then, in template:

{% load html5type %}
<input type={{ field.value | html5type }} ></input>

Of course you can extend the html5type function further for other types

Caveat: Numeric fields need a default value for the above to work

like image 41
Mabura Ze Guru Avatar answered Oct 07 '22 15:10

Mabura Ze Guru


Instead of RegexValidator, give validation in forms attributes only like...

class StaffDetailsForm(forms.ModelForm):
    number = forms.CharField(required=True,widget=forms.TextInput(attrs={'class':'form-control' , 'autocomplete': 'off','pattern':'[0-9]+', 'title':'Enter numbers Only '}))

and so on...

Else you will have to handle the error in views. It worked for me try this simple method... This will allow users to enter only Number only

like image 40
Javed Avatar answered Oct 07 '22 16:10

Javed