SumanKalyan
SumanKalyan

Reputation: 1761

File Field can't hold the file when another validation error occurred in wtforms

I am trying to validate the email and phone number in my form. This is done but when this validation error occurred , the file field can't hold the uploaded file. My form is given below.

forms.py

from wtforms import Form ,SelectField,StringField, validators  , IntegerField , DateField , SelectMultipleField , FileField ,widgets
            
from wtforms.validators import StopValidation, ValidationError
            
def customvalidatorForAdImage(form, field):
                allowed_file = ['jpg','jpeg','png','gif']
                if form.image.data:
                    if form.image.data.split('.',1)[1] not in allowed_file:
                        raise ValidationError("Please enter a valid image file")    
class CreateAdForm(Form):
            ad_name = StringField("Ad Name", [validators.DataRequired("Ad name is required")])
            advertiser_name =SelectField("Advertiser Name" , coerce=int)
            ad_type = SelectField("Ad Type" ,  choices =zip( ad_type_categories , ad_type_cat_lebels))
            image = FileField("Image" , [customvalidatorForAdImage, validators.DataRequired("Image is required")])
            url = StringField("URL" , [validators.DataRequired("URL is required")])
            contact_name = StringField("Contact Name" , [validators.DataRequired("Contact Name is required")])
            contact_email = StringField("Contact Email" , [validators.DataRequired("Contact Email is required"), validators.Email("Please enter a valid email")])
            contact_phone = StringField("Contact Phone" , [validators.DataRequired("Contact Phone is required"), validators.Regexp("^(\+\d{1,3}[- ]?)?\d{10}$", message="Please enter a valid phone number")])
            status = SelectField("Status" , choices = zip(status_categories , status_cat_lebles))      
            

And my ad.html file is given below:

ad.html

{% extends "base.html" %}
{% set title = "Admin Manage Advertisers" %}
{% block head_css %}

{% endblock %}
{% block main_body %}
<div class="container">
    <div class="row">
        <div class="col-sm-8 col-sm-offset-2">
            {% if err_msg %}
             <div class="alert alert-danger alert-msg-with-icon" role="alert"> 
             <i class="icon-exclamation-sign" style="font-size:60px;color:#B94A48;"></i> 
             <p>{{err_msg}}<br> If you believe this message is in error, please reach out to <a href='mailto:[email protected]' class="alert-link">[email protected]</a></p>
             </div>
            {% endif %}
            <h1 class="text-center"><strong>Create a New Ad</strong></h1>
            <form action="/create-ad" enctype="multipart/form-data" method="POST">
              <div class="form-group">
                {{ ad_form.ad_name.label }}
                {{ ad_form.ad_name(class_="form-control", **{"data-parsley-required":"true", 
                                                          "data-parsley-required-message":"Ad name is required"}) }}
                
                <span class="help-block"></span>
              </div>
             <div class="row">
                <div class="col-md-5">
               <div class="form-group" >
                {{ ad_form.advertiser_name.label }}
                {{ ad_form.advertiser_name(class_="form-control" , **{"data-parsley-required":"true", 
                                                          "data-parsley-required-message":"Advertiser name is required"}) }}
                
                                                          
                <span class="help-block"></span>
              </div>
              </div>
               <div class="col-md-5 col-md-offset-2">
              <div class="form-group" >
                {{ ad_form.ad_type.label }}
                {{ ad_form.ad_type(class_="form-control", **{"data-parsley-required":"true", 
                                                          "data-parsley-required-message":"Ad type is required"
                                                          }) }}
                <span class="help-block"></span>
              </div>
              </div>
              </div>
              <div class="row">
                <div class="col-md-5">
              <div class="form-group {{ 'has-error' if ad_form.image.errors}}">
                {{ ad_form.image.label }}
                {{ ad_form.image( **{"data-parsley-required":"true", 
                                                          "data-parsley-required-message":"Image is required",
                                                          
                                                          }) }}
                <span class="help-block">{{ ad_form.image.errors[0] if ad_form.image.errors }}</span>
              </div>
              </div>
             <div class="col-md-5 col-md-offset-2">
                <div class="form-group" >
                {{ ad_form.status.label }}
                {{ ad_form.status(class_="form-control", **{"data-parsley-required":"true", 
                                                          "data-parsley-required-message":"Status is required"
                                                          }) }}
                <span class="help-block"></span>
              </div>
              </div>
              </div>
              <div class="form-group" >
                {{ ad_form.url.label }}
                {{ ad_form.url(class_="form-control", **{"data-parsley-required":"true", 
                                                          "data-parsley-required-message":"URL is required"
                                                          }) }}
                <span class="help-block"></span>
              </div>
              <div class="form-group">
                {{ ad_form.contact_name.label }}
                {{ ad_form.contact_name(class_="form-control", **{"data-parsley-required":"true", 
                                                          "data-parsley-required-message":"Contact Name is required"
                                                          }) }}
                <span class="help-block"></span>
              </div>
              <div class="form-group {{ 'has-error' if ad_form.contact_email.errors}}" >
                {{ ad_form.contact_email.label }}
                {{ ad_form.contact_email(class_="form-control", **{"data-parsley-required":"true", 
                                                          "data-parsley-required-message":"Contact Email is required"
                                                          }) }}
                <span class="help-block">{{ ad_form.contact_email.errors[0] if ad_form.contact_email.errors }}</span>
              </div>
              <div class="form-group {{ 'has-error' if ad_form.contact_phone.errors}}" >
                {{ ad_form.contact_phone.label }}
                {{ ad_form.contact_phone(class_="form-control", **{"data-parsley-required":"true", 
                                                          "data-parsley-required-message":"Contact Phone is required"
                                                          }) }}
                <span class="help-block">{{ ad_form.contact_phone.errors[0] if ad_form.contact_phone.errors }}</span>
              </div>
              
              <button type="submit" class="btn btn-primary btn-block">SUBMIT</button>
            </form>
        </div>
    </div>
</div>
{% endblock %}
{% block contact_us_block %}
{% endblock %}
{% block js_block %}
{{super()}}

<script>
$(document).ready(function(){
    
    $("div.container form").parsley({
        successClass: "",
        errorClass: "has-error",
        classHandler: function(el) {
            return el.$element.closest(".form-group");
        },
        errorsWrapper: "<span class='help-block'></span>",
        errorTemplate: "<span></span>"
    });
    
})
</script>
{% endblock %} 

And see the screen-shot before form submit.Here I have selected a image file and invalid email.enter image description here

But when I click the submit button , its show the email validation error but can't hold the selected image file. How can i fix that? See the screen-shot after submit. It shown "No file selected" in the file field but I already have selected the file. Thanks.enter image description here

Upvotes: 1

Views: 454

Answers (1)

Doobeh
Doobeh

Reputation: 9440

It's a feature of HTML, you can't easily work around it. If the server could send a html page to the client with a little extra information saying "Hey, you tried to upload REALLY_SECRET_FILE, please automatically attach it again please" you could easily picture it being used for bad purposes (especially since you could hide the file field with CSS).

So, you have two remaining options that come to mind— you say the form didn't validate, but you could optionally just validate the file field first, then store that on the server, then if the remaining form failed validation, you could remove the form field from the pre-populated form field you send back to the client and replace it with, say, a thumbnail of the already uploaded file.

The other option is to lean harder on the client-side of the process— do more client-side validation to reduce the chances of a form ever being submitted that would fail validation, but of course, still validate on the server-side to trap odd or naughty situations.

Upvotes: 1

Related Questions