验证错误时只保存表单的一部分

时间:2015-11-05 19:12:17

标签: python django

我试图在验证失败时消除页面刷新时的数据丢失。在验证错误之后刷新表单时,除了导致错误的字段外,所有字段都为空。如何刷新页面,显示验证错误并且仍然填充所有div中的所有字段?

提前致谢!

我的代码显示如下:

views.py

class CreateListingView(CreateView):
    template_name = 'listing/listing.html'
    model = Listing
    form_class = ListingForm
    # success_url = '/add-listing/'

def get_success_url(self):
    return reverse('store') + "?success=true"

def dispatch(self, request, *args, **kwargs):
    if self.request.user.is_authenticated():
        if not self.request.user.has_company():
            return HttpResponseRedirect(reverse('get_paid'))
        elif not self.request.user.has_shipping():
            return HttpResponseRedirect(reverse('get_paid'))
        elif not self.request.user.has_bank():
            return HttpResponseRedirect(reverse('get_paid'))
        else:
            return super(CreateListingView, self).dispatch(request, *args, **kwargs)
    else:
        return HttpResponseRedirect(reverse('create_user'))

def get_initial(self):
    return {'company_profile': self.request.user.company}

def get_form_kwargs(self):
    kwargs = super(CreateListingView, self).get_form_kwargs()
    if self.request.method in ('POST', 'PUT'):
        kwargs['data']['price'] = kwargs['data']['price'].replace(',','')
    return kwargs   

forms.py

class ListingForm(forms.ModelForm):
    caliber_firearm = forms.CharField(required=False,     widget=forms.TextInput(attrs={'class': 'req'}))
    caliber_ammo = forms.CharField(required=False)

tags = forms.CharField(required=False)
img_0 = forms.ImageField(required=False, widget=forms.FileInput(attrs={'class': 'image-input'}))
img_1 = forms.ImageField(required=False, widget=forms.FileInput(attrs={'class': 'image-input'}))
img_2 = forms.ImageField(required=False, widget=forms.FileInput(attrs={'class': 'image-input'}))
img_3 = forms.ImageField(required=False, widget=forms.FileInput(attrs={'class': 'image-input'}))
img_4 = forms.ImageField(required=False, widget=forms.FileInput(attrs={'class': 'image-input'}))

class Meta:
    model = Listing
    exclude = ['copy', 'caliber']
    widgets = {
        'title': forms.TextInput(attrs={'class': 'title-listing'}),
        'listing_type': forms.RadioSelect(),
        'upc': forms.TextInput(attrs={'class': 'upc'}),
        'category': forms.Select(attrs={'class': 'short-input', 'required': 'True'}),
        'price': forms.TextInput(attrs={'class': 'price dollar req'}),
        'list_price': forms.TextInput(attrs={'class': 'list_price_input'}),
        'quantity': forms.TextInput(attrs={'class': 'qty req'}),
        'description': forms.Textarea(attrs={'class': 'description req'}),
        'estimated_ship_days': forms.TextInput(attrs={'class': 'qty req', 'placeholder': 'Days'}),
        'capacity': forms.TextInput(attrs={'class': 'req'}),
        'weight_pounds': forms.TextInput(attrs={'class': 'weight req', 'placeholder': 'Pounds'}),
        'weight_ounces': forms.TextInput(attrs={'class': 'weight', 'placeholder': 'Ounces'}),
        'barrel_length': forms.TextInput(attrs={'class': 'req', 'placeholder': 'Inches'}),
        'overall_length': forms.TextInput(attrs={'class': 'req', 'placeholder': 'Inches'}),
        'company_profile': forms.HiddenInput(),
        'shipping_zip_code': forms.TextInput(attrs={'placeholder': 'Your shipping zip code'}),
    }

    error_messages = empty_errors

def clean(self):
    listing_type = self.cleaned_data.get('listing_type')
    if self.cleaned_data.get('img_0') is None and \
                    self.cleaned_data.get('img_1') is None and \
                    self.cleaned_data.get('img_2') is None and \
                    self.cleaned_data.get('img_3') is None and \
                    self.cleaned_data.get('img_4') is None:

        self.add_error('img_0', 'One photo must be uploaded')

    if listing_type == 'Firearm':
        if self.cleaned_data.get('caliber_firearm', None) is None:
            self.add_error('caliber_firearm', 'This field is required')
        else:
            self.cleaned_data['caliber'] = self.cleaned_data.get('caliber_firearm')
        if self.cleaned_data.get('capacity', None) is None:
            self.add_error('capacity', 'This field is required')
        if self.cleaned_data.get('weight_pounds', None) is None:
            self.add_error('weight_pounds', 'This field is required')
        if self.cleaned_data.get('weight_ounces', None) is None:
            self.add_error('weight_ounces', 'This field is required')
        if self.cleaned_data.get('barrel_length', None) is None:
            self.add_error('barrel_length', 'This field is required')
        if self.cleaned_data.get('overall_length', None) is None:
            self.add_error('overall_length', 'This field is required')
    elif listing_type == 'Ammo':
        if self.cleaned_data.get('caliber_ammo', None) is not None:
            self.cleaned_data['caliber'] = self.cleaned_data.get('caliber_ammo')

    if self.cleaned_data.get('shipping_zip_code') is None or \
                    self.cleaned_data.get('shipping_weight') is None or \
                    self.cleaned_data.get('shipping_height') is None or \
                    self.cleaned_data.get('shipping_length') is None or \
                    self.cleaned_data.get('shipping_width') is None:

        self.add_error('shipping_weight', 'Shipping information is not complete')

    return self.cleaned_data

模板

{% extends 'base.html' %}
{% load staticfiles %}
{% block head %}

    <title>Dealer Direct by FFL Design</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet"
          type="text/css"
          href="{% static 'listing/css/listing.css' %}">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
    <script src="{% static 'listing/js/listing.js' %}"></script>

    <!-- Start of ffldesign Zendesk Widget script -->
    <script>/*<![CDATA[*/window.zEmbed||function(e,t){var n,o,d,i,s,a=[],r=document.createElement("iframe");window.zEmbed=function(){a.push(arguments)},window.zE=window.zE||window.zEmbed,r.src="javascript:false",r.title="",r.role="presentation",(r.frameElement||r).style.cssText="display: none",d=document.getElementsByTagName("script"),d=d[d.length-1],d.parentNode.insertBefore(r,d),i=r.contentWindow,s=i.document;try{o=s}catch(c){n=document.domain,r.src='javascript:var d=document.open();d.domain="'+n+'";void(0);',o=s}o.open()._l=function(){var o=this.createElement("script");n&&(this.domain=n),o.id="js-iframe-async",o.src=e,this.t=+new Date,this.zendeskHost=t,this.zEQueue=a,this.body.appendChild(o)},o.write('<body onload="document._l();">'),o.close()}("https://assets.zendesk.com/embeddable_framework/main.js","ffldesign.zendesk.com");/*]]>*/</script>
    <!-- End of ffldesign Zendesk Widget script --> 

{% endblock %}
{% block body %}
<body>
    <div class="listing">
        <p class="ffl">Add a new listing</p>
        <form action="{% url 'add-listing' %}" method="post" enctype="multipart/form-data">
            <div class="errors">{{ form.shipping_weight.errors }}</div>
            {% csrf_token %}
            <div class="photos">
                <p class="ffl-small">Photos</p>
                <p class="desc" id="photos-desc">Must add at least one photo.</p>
                <ul>
                    <li id="photo_0">
                        <div id="input_photo_0">
                            <img src="{% static 'listing/images/add-photo.png' %}" class="add-photo">
                            <p><button type="button" class="active-button">Add Photo</button></p>
                            {{ form.img_0 }}
                        </div>
                        <div id="display_photo_0" class="hidden">
                            <img src="" width="143" height="105" id="img_view_0" class="item-image">
                            <button type="button" class="remove-zoom active-button magnify"><img src="{% static 'listing/images/zoom.png' %}" width="18" height="18"></button><button type="button" class="remove-zoom active-button delete_photo"><img src="{% static 'listing/images/remove.png' %}"></button>
                        </div>
                    </li>
                    <li id="photo_1">
                        <div id="input_photo_1">
                            <img src="{% static 'listing/images/add-photo.png' %}" class="add-photo">
                            <p><button type="button" class="active-button">Add Photo</button></p>
                            {{ form.img_1 }}
                        </div>
                        <div id="display_photo_1" class="hidden">
                            <img src="" width="143" height="105" id="img_view_1" class="item-image">
                            <button type="button" class="remove-zoom active-button magnify"><img src="{% static 'listing/images/zoom.png' %}" width="18" height="18"></button><button type="button" class="remove-zoom active-button delete_photo"><img src="{% static 'listing/images/remove.png' %}"></button>
                        </div>
                    </li>
                    <li id="photo_2">
                        <div id="input_photo_2">
                            <img src="{% static 'listing/images/add-photo.png' %}" class="add-photo">
                            <p><button type="button" class="active-button">Add Photo</button></p>
                            {{ form.img_2 }}
                        </div>
                        <div id="display_photo_2" class="hidden">
                            <img src="" width="143" height="105" id="img_view_2" class="item-image">
                            <button type="button" class="remove-zoom active-button magnify"><img src="{% static 'listing/images/zoom.png' %}" width="18" height="18"></button><button type="button" class="remove-zoom active-button delete_photo"><img src="{% static 'listing/images/remove.png' %}"></button>
                        </div>
                    </li>
                    <li id="photo_3">
                        <div id="input_photo_3">
                            <img src="{% static 'listing/images/add-photo.png' %}" class="add-photo">
                            <p><button type="button" class="active-button">Add Photo</button></p>
                            {{ form.img_3 }}
                        </div>
                        <div id="display_photo_3" class="hidden">
                            <img src="" width="143" height="105" id="img_view_3" class="item-image">
                            <button type="button" class="remove-zoom active-button magnify"><img src="{% static 'listing/images/zoom.png' %}" width="18" height="18"></button><button type="button" class="remove-zoom active-button delete_photo"><img src="{% static 'listing/images/remove.png' %}"></button>
                        </div>
                    </li>
                    <li id="photo_4">
                        <div id="input_photo_4">
                            <img src="{% static 'listing/images/add-photo.png' %}" class="add-photo">
                            <p><button type="button" class="active-button">Add Photo</button></p>
                            {{ form.img_4 }}
                        </div>
                        <div id="display_photo_4" class="hidden">
                            <img src="" width="143" height="105" id="img_view_4" class="item-image">
                            <button type="button" class="remove-zoom active-button magnify"><img src="{% static 'listing/images/zoom.png' %}" width="18" height="18"></button><button type="button" class="remove-zoom active-button delete_photo"><img src="{% static 'listing/images/remove.png' %}"></button>
                        </div>
                    </li>
                    <li class="desc">
                        For best results, use high quality jpeg or gif files that are at least 570 px wide.
                    </li>
                </ul>
            </div>
            <div class="select-type">
                <p class="ffl-small">Select listing type</p>
                {% for radio in form.listing_type %}
                    {{ radio }}
                {% endfor %}
{#                <label><input type="radio" name="listing" checked>Firearms</label>#}
{#                <label><input type="radio" name="listing">Ammo</label>#}
{#                <label><input type="radio" name="listing">Optics</label>#}
{#                <label><input type="radio" name="listing">Apparel</label>#}
{#                <label><input type="radio" name="listing">Other</label>#}
            </div>
            <div class="details">
                <p class="ffl-small">Listing Details</p>
                <p><label for="id_title">Title<span>&#42;</span></label><input type="text" id="id_title" name="title" class="title-listing" required><span class="desc">Describe your item using words and phrases people would use in a search.</span>
                    <span class="title-error">Error: you cannot use a period in the title name.</span>
                </p>
                <p><label for="id_upc">UPC</label><input type="text" name="upc" id="id_upc" class="upc" maxlength="12"></p>
                <p><label for="id_category">Category<span>&#42;</span></label>
                    {{form.category}}
                </p>
                <p>
                    <label for="id_price">Cost<span>&#42;</span></label><input type="number" name="price" id="id_price" class="price dollar req" min=0 step="0.01">
                    <span class="list_price_text">List Price:<input type="number" name="list_price" id="id_list_price" class="list_price_input" step="0.01" readonly></span>
                    <span class="list_price_desc">The "List Price" is automatically calculated with Dealer Direct seller fees. This price is what the dealer will see. The "Cost" field is the amount you will be paid.</span>
                </p>
                <p><label for="id_quantity">Quantity<span>&#42;</span></label><input type="text" name="quantity" id="id_quantity" class="qty req"></p>
                <p><label for="id_description" class="textarea-label">Description<span>&#42;</span></label><textarea name="description" id="id_description" class="description req"></textarea></p>
                <p><label for="id_estimated_ship_days">Days to ship:<span>&#42;</span></label><input type="text" name="estimated_ship_days" id="id_estimated_ship_days" class="qty req" placeholder="days"></p>

                {% for field in form.hidden_fields %}
                    {{ field }}
                {% endfor %}
            </div>
            <div class="details ammo type-ammo">
                <p class="ffl-small">Ammo Details</p>
                <p><label for="id_rounds">Rounds per box</label>{{ form.rounds }}</p>
                <p><label for="id_caliber_ammo">Caliber/Gauge</label>{{ form.caliber_ammo }}</p>
                <p><label for="id_weight">Weight</label>{{ form.weight }}</p>
                <p><label for="id_muzzle_velocity">Muzzle Velocity</label>{{ form.muzzle_velocity }}</p>
                <p><label for="id_length">Length</label>{{ form.length }}</p>
                <p><label for="id_ammo_type">Type</label>{{ form.ammo_type }}</p>
            </div>
            <div class="details ammo type-firearm">
                <p class="ffl-small">Firearm Details</p>
                <p><label for="id_caliber_firearm">Caliber<span>&#42;</span></label>{{ form.caliber_firearm }}</p>
                <p><label for="id_capacity">Capacity<span>&#42;</span></label>{{ form.capacity }}</p>
                <p><label for="id_weight_pounds">Weight<span>&#42;</span></label>{{ form.weight_pounds }}<label for="id_weight_ounces" class="weight-label"></label>{{ form.weight_ounces }}</p>
                <p><label for="id_barrel_length">Barrel Length<span>&#42;</span></label>{{ form.barrel_length }}</p>
                <p><label for="id_overall_length">Overall Length<span>&#42;</span></label>{{ form.overall_length }}</p>
                <p><label for="id_finish">Finish</label>{{ form.finish }}</p>
            </div>
            <div class="details optics type-optics">
                <p class="ffl-small">Optics Details</p>
                <p><label for="id_magnification">Magnification</label><input id="id_magnification" name="magnification" type="text"></p>
                <p><label for="id_field_of_view">Field of View</label><input id="id_field_of_view" name="field_of_view" type="text"></p>
                <p><label for="id_reticle">Reticle</label><input id="id_reticle" name="reticle" type="text"></p>
                <p><label for="id_objective_lens">Objective Lens</label><input id="id_objective_lens" name="objective_lens" type="text"></p>
                <p><label for="id_eye_relief">Eye Relief</label><input id="id_eye_relief" name="eye_relief" type="text"></p>
                <p><label for="id_max_elevation_adjustment">Max Elevation Adjustment</label><input id="id_max_elevation_adjustment" name="max_elevation_adjustment" type="text"></p>
                <p><label for="id_max_windage_adjustment">Max Windage<br/>Adjustment</label><input id="id_max_windage_adjustment" name="max_windage_adjustment" type="text"></p>
                <p><label for="id_length_optics">Length</label><input id="id_length_optics" name="length" type="text"></p>
                <p><label for="id_weight_optics">Weight</label><input id="id_weight_optics" name="weight" type="text"></p>
                <p><label for="id_battery">Battery</label><input id="id_battery" name="battery" type="text"></p>
                <p><label for="id_dot_size">DOT Size</label><input id="id_dot_size" name="dot_size" type="text"></p>
                <p><label for="id_finish_optics">Finish</label><input id="id_finish_optics" name="finish" type="text"></p>
            </div>
            <div class="details apparel type-apparel">
                <p class="ffl-small">Apparel Details</p>
                <p><label for="id_shirt_size">Size</label>
                    {{ form.shirt_size }}
                </p>
                <p><label for="id_shirt_color">Color</label><input id="id_shirt_color" name="shirt_color" type="text"></p>
            </div>
            <div class="search">
                <p class="ffl-small">Search Terms</p>
                <p class="desc">Help dealers find this product by using accurate and descriptive words or phrases.</p>
                <ul class="search-ul">
                    <li>
                        <span class="tags"><label for="id_tags">Tags</label></span>
                        <span class="desc">Optional</span>
                    </li>
                    <li>
                        <label><input type="text" name="tags" id="id_tags" placeholder="example: ar15, iron sights, glock holster, etc" class="tag-input"><span class="desc left">10 left</span></label>
                        <p class="tags-wrapper">must separate each tag by a comma</p>
                        <p id="tag-list"></p>
                    </li>
                    <li>
                        <span class="desc">
                            We highly recommend using all 10 tags for<br />your listing to get
                            found. Use words you think<br />dealers would use to search for this product.
                        </span>
                    </li>
                </ul>
            </div>
            <div class=" details shipping">
                <p class="ffl-small">Shipping</p>
                <p class="desc">For realistic shipping expectations, please provide accurate product shipping information below.</p>
                <div class="errors">{{ form.shipping_zip_code.errors }}{{ form.shipping_weight.errors }}</div>
                {% comment %}
                <p class="zip"><label for="">Zip Code</label><input name="" type="text" placeholder="Your shipping zip code"></p>
                <p class="shipping-weight"><label for="">Weight</label><input name="" type="text"><label for=""></label><input name="" type="text"></p>
                <p class="dimensions"><label for="">Dimensions</label><input name="" type="text"><label for=""></label><input name="" type="text"><label for=""></label><input name="" type="text"></p>
                {% endcomment %}
                <p class="zip">
                    <label for="id_shipping_zip_code">Zip Code</label>
                    {{form.shipping_zip_code}}
                </p>
                <p class="shipping-weight">
                    <label for="id_shipping_weight">Weight</label>
                    {{form.shipping_weight}}
                </p>
                <p class="dimensions">
                    <label for="">Dimensions</label>
                    {{form.shipping_length}}
                    <label for=""></label>
                    {{form.shipping_width}}
                    <label for=""></label>
                    {{form.shipping_height}}
                </p>
            </div>
            <button class="submit-btn active-button">Submit Listing</button>
        </form>
        <div class="wrapper">
            <div class="">
                <button class="active-button">Close</button>
                <img src="{% static 'listing/images/example-img.png' %}">
            </div>
        </div>
    </div>

    <div id="spacer"></div>
</body>
{% endblock %}

1 个答案:

答案 0 :(得分:0)

比我想象的要简单得多。只需要添加&#39; value =&#34; {{form.field_name.value}}&#34;&#39;每个输入。

<input type="text" class="foo" value="{{ form.field_name.value }}"/>

我还发现每个django模板标签都已保存。用django <input>变量替换每个{{ form.field_name }}标记也解决了这个问题。