jsanchezs
jsanchezs

Reputation: 2070

Django empty form field validation is not working with clean method

I got a django form and i want to validate that fields are not empty when im going to save, let's say for example the "description" field (charfield)....this is my form.py code :

from django.core.exceptions import ValidationError

class CostItemsForm(ModelForm):

    groupid = forms.CharField(required=True)

    def __init__(self, *args, **kwargs):
        super(CostItemsForm, self).__init__(*args, **kwargs)

    class Meta:
        model = CostItems
        fields = [
                    'description', 
                    'usd_value', 
                    'rer',
                    'pesos_value', 
                    'supplier', 
                    'position',
                    'observations',
                    'validity_date',
                ]

    def clean_description(self):
        des = self.cleaned_data['description']
        if des==None:
            raise ValidationError("Description cannot be empty")
        return des

But nothing happens, already tried returning like this: return self.cleaned_data and return clean_description but still the same.

This is my view.py:

class CostItemInsert(View):
    template_name='cost_control_app/home.html'

    def post(self, request, *args, **kwargs):
        if request.user.has_perm('cost_control_app.add_costitems'):
            form_insert = CostItemsForm(request.POST)
            if form_insert.is_valid():
                form_save = form_insert.save(commit = False)
                form_save.save(force_insert = True) 
                messages.success(request, "Record created")
            else:
                messages.error(request, "Could not create record, please check your form")
        else:
            messages.error(request, "Permission denied")
        form_group = GroupsForm()
        form_subgroup= SubGroupsForm()
        form_cost_item = CostItemsForm()
        return render(request, self.template_name,{
                                    "form_subgroup":form_subgroup,
                                    "form_cost_item":form_cost_item,
                                    "form_group":form_group,
                                })  

And the costitems model :

class CostItems(ModelAudit):
    cost_item = models.AutoField(primary_key = True, verbose_name = 'Item de costo')
    group = models.ForeignKey(Groups, verbose_name = 'Grupo')
    description = models.CharField(max_length = 100, verbose_name =' Descripcion')
    usd_value = models.IntegerField(verbose_name ='Valor en USD')
    rer = models.IntegerField(verbose_name = 'TRM negociado')
    pesos_value = models.IntegerField(verbose_name = 'Valor en pesos')
    supplier = models.ForeignKey(Suppliers, verbose_name = 'Proveedor')
    position = models.ForeignKey(Positions, verbose_name = 'Cargo')
    observations = models.TextField(max_length = 500, verbose_name = 'Observación')
    validity_date = models.DateField(verbose_name = 'Fecha de vigencia')

    def __str__(self):
        return self.description

    class Meta:
            ordering = ['cost_item']
            verbose_name = 'Item de costos'
            verbose_name_plural = 'Items de costo'

And here is the modal code i call from a input button inside the html template where i call the view :

<div class="modal fade bs-example-modal-lg" id="myModals" tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel">
  <div class="modal-dialog modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
        <h4 class="modal-title" id="myModalLabel">Registrar item de costo</h4>
      </div>
      <form method="post" action="{% url 'cost_control_app:cost_item_insert' %}">
      {% csrf_token %}
          <div class="modal-body">
            <br/>
            <div class="row">
                {%include "partials/field.html" with field=form_cost_item.groupid|attr:"readonly:True" %}<br clear="all"/>
                {%include "partials/field.html" with field=form_cost_item.description %}<br clear="all"/>
                {%include "partials/field.html" with field=form_cost_item.usd_value|attr:"value:0"|attr:"id:id_usd_value" %}<br clear="all"/>
                {%include "partials/field.html" with field=form_cost_item.rer|attr:"value:0"|attr:"id:id_rer_value" %}<br clear="all"/>
                {%include "partials/field.html" with field=form_cost_item.pesos_value|attr:"value:0"|attr:"id:id_pesos_value" %}<br clear="all"/>
                {%include "partials/field.html" with field=form_cost_item.supplier %}<br clear="all"/>
                {%include "partials/field.html" with field=form_cost_item.position %}<br clear="all"/>
                {%include "partials/field.html" with field=form_cost_item.observations %}<br clear="all"/>
                {%include "partials/field.html" with field=form_cost_item.validity_date %}<br clear="all"/>
                </br>

            </div>

          </div>
          <div class="modal-footer">
            <button type="button" class="btn btn-default" data-dismiss="modal">Cerrar</button>
            <button type="submit" class="btn btn-primary">Guardar</button>
          </div>
       </form>
    </div>
  </div>
</div> 

Last, partials/fields.html too :

{% load widget_tweaks%}
<div class="col-md-10">
    <div class="form-group {% if field.errors %}has-error{% endif %}">
        <label class="col-sm-2 control-label">{% if field.field.required %}{% endif %}{{ field.label }}<label style="color:red">*</label></label>
            <div class="col-sm-10">
                {% if type == 'check' %}
                    {{ field|add_class:"check" }}
                {% elif type == 'radio' %}
                    {{ field|add_class:"radio" }}
                {% else %}                
                    {{ field|add_class:"form-control" }} 
                {% endif %}
            </div>
            {% for error in field.errors %}
                <div class="error_msg">- {{ error }}</div>
            {% endfor %}
    </div>
</div>

Any help ?

Thanks in advance

Upvotes: 3

Views: 14028

Answers (2)

Krishna G Nair
Krishna G Nair

Reputation: 268

If you are trying to show the form errors in the template you should pass the errors to the template. In your case the view should be something like the following.

def post(self, request, *args, **kwargs):
    if request.user.has_perm('cost_control_app.add_costitems'):
        form_insert = CostItemsForm(request.POST)
        if form_insert.is_valid():
            form_save = form_insert.save(commit = False)
            form_save.save(force_insert = True) 
            messages.success(request, "Record created")
        else:
            messages.error(request, "Could not create record, please check your form")
            form_group = GroupsForm()
            form_subgroup= SubGroupsForm()
            return render(request, self.template_name,{
                            "form_subgroup":form_subgroup,
                            "form_cost_item":form_insert,
                            "form_group":form_group,
                        })   

    else:
        messages.error(request, "Permission denied")
    form_group = GroupsForm()
    form_subgroup= SubGroupsForm()
    form_cost_item = CostItemsForm()
    return render(request, self.template_name,{
                                "form_subgroup":form_subgroup,
                                "form_cost_item":form_cost_item,
                                "form_group":form_group,
                            })  

I can see that the fields in the model are required fields by default. So anyway it will raise validation error. All you need to do is to pass the error form to template if form is invalid as above.

Upvotes: 0

Sayse
Sayse

Reputation: 43330

des never will equal None, the default value will at least be an empty string

if not des: should be enough to satify your if statement when des is empty

If all you really want to check is if its empty or not you can do that in the model by setting blank to False

description = models.CharField(max_length = 100, blank=False, verbose_name =' Descripcion')

If a field has blank=True, form validation will allow entry of an empty value. If a field has blank=False, the field will be required.


Yeah, but isn't validation error supossed to show the alert inside the form before user can proceed to save ??

Yes it is but you override the form before it is ever shown to the user, this can easily be solved by defining the forms at the top of your method then overriding them further down

   def post(self, request, *args, **kwargs):
        form_group = GroupsForm()
        form_subgroup= SubGroupsForm()
        form_cost_item = CostItemsForm()
        if request.user.has_perm('cost_control_app.add_costitems'):
            form_cost_item = CostItemsForm(request.POST)
            if form_cost_item.is_valid():
                form_save = form_cost_item.save(commit = False)
                form_save.save(force_insert = True) 
                messages.success(request, "Record created")
            else:
                messages.error(request, "Could not create record, please check your form")
        else:
            messages.error(request, "Permission denied")
        return render(request, self.template_name,{
                                    "form_subgroup":form_subgroup,
                                    "form_cost_item":form_cost_item,
                                    "form_group":form_group,
                                })  

Upvotes: 6

Related Questions