0

I’ve built a web app with Django. Although the FloatField was designated as ‘weight’ & ‘height’ model fields, my application refused to input the float value, and only accepts integer. I attempt to declare the FloatField at the forms, but it doesn’t seem to work. I have no idea what’s cause and desire to know how to be able to input the float value with solving this problem. Following is my code and Django is version 2.0

# Model.py
class Profile(models.Model):

    class Meta(object):
        db_table='profile'

    user=models.OneToOneField(settings.AUTH_USER_MODEL,on_delete=models.CASCADE,
                          primary_key=True)
    weight=models.FloatField(_('weight'),blank=False)
    height=models.FloatField(_('height'),blank=False)
    bmi=models.FloatField(_('BMI'))


    def __str__(self):
        return self.user.nickname


# Form.py
class BioRegisterForm(forms.ModelForm):
    class Meta:
        model=Profile
        fields=('weight','height')
        help_texts={'weight':('Kg単位で入力してください'),'height':('cm単位で入力して下さい')}

    def __init__(self,*args,**kwargs):
        super().__init__(*args,**kwargs)
        self.fields['weight'].widget.attrs={'placeholder':'Weight','required':True}
        self.fields['height'].widget.attrs={'placeholder':'Height','required':True}

    def clean_hight(self):
        value=self.cleaned_data.get('height')
        if value<50:
            raise forms.ValidationError('Type in with 「cm」')
        return value

# View.py
class BioRegisterView(CreateView):
    model=Profile
    template_name='mysite/bioregister.html'
    form_class=BioRegisterForm
    success_url=reverse_lazy('mysite/profile.html')

and the following is the bioregister.html, page in question

<form method='post' action="">
{% for field in form %}
<div>
    <div class='entry'>
        {{field}}
    </div>
    {%if field.errors %}
    <p> {{field.errors.0}}</p>
    {% endif %}
</div>
{%  endfor %}
{% csrf_token %}
<input type="submit" value="Register" class='bottun2'>
</form>

enter image description here

Thank you

2
  • I think you need to pass default argument.try this. weight=models.FloatField(_('weight'),default=value) height=models.FloatField(_('height'),default=value) Commented Jan 21, 2020 at 5:52
  • Thank @ Dinesh. I attempt set the default value, for example 65.5 into the weight field and the webpage actually displayed 65.5 as default value. What’s more it could accept the value of ◯◯.5, for example 64.5, 47.5 or 78.5, but unfortunately turned down input the value other than ◯◯.5 for example 64.3, 47.3 or 78.7. Commented Jan 22, 2020 at 21:33

1 Answer 1

1

First of all, as stated in the docs:

The default form widget for this field is a NumberInput when localize is False or TextInput otherwise.

As you are asking about the spinners in your widget: This is just the way your browsers renders a NumberInput. You can make them invisible using css.

However, for the NumberInput to accept any decimal value the step attribute of the input must be set to 'any'. This is waht django normally does when creating the widget for a FloatField.

But you are manually setting the attributes of your widget and your are setting no step attribute. I believe the default value if no stap value is provided is 1, meaning you can only enter integers.

I would recommend setting your attributes as follows in order to overcome this issue:

self.fields['weight'].widget.attrs.update({'placeholder':'Height','required':True})

This way you do not miss anything important django sets by default.

Some additional information:

widget.attrs is a dict with the attributes django is using to render the widget on the html page. For some widgets django already creates attributes when creating the field. So in your case after the call super().__init__(*args, **kwargs) the attrs of the float input widget is this dict: {'step': 'any'}.

Now with your original line self.fields['weight'].widget.attrs={'placeholder':'Weight','required':True} your are resetting the attrs dict to {'placeholder':'Weight','required':True}, meaning your attrs does not have a 'step' key anymore. The default behaviour of a NumberInput without a 'step' attribute is to accept integers only.

So when you update the attrs dict (as shown above) instead of replacing it you make sure that the values in the dict which django has already set and which you do not want to change are left untouched and the attributes you want to add/change are put into the existing dict.

Sign up to request clarification or add additional context in comments.

3 Comments

Thank @chris for providing advisable information. Your answer was just right, solving my trouble. On the other hand, a question raised. That are why does your suggestion (setting ‘.update()’) make the input of float accept, and what’s real cause of the rejection? As far as my poor knowledge, the attribute (.update()) can change something…(right?), it mean this alter ‘NumberInput’ too ‘TextInput’? I’m glad if you would provide something of clear answer Thank you
@GenzoIto Was a pleasure! I added some background information to my answer
Thanks. Your additional explanation made me so clear, and I got !

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.