2

I couldn't show django validation errors on my bootstrap modal form. I need to set client_phone field on the form was no less than 13 characters, if not - show error and highlight the field. Django - 1.10, Bootstrap 3

Here is the code:

Model:

class Order(models.Model):
    order_date = models.DateTimeField(auto_now_add=True, blank=True)
    client_phone = models.CharField(max_length=18)
    client_email = models.EmailField(max_length=50)

then ModelForm:

class OfferForm(ModelForm):
    class Meta:
        model = Order
        fields = ['client_phone', 'client_email']
        widgets = {
            'client_phone': TextInput(attrs={'class': 'form-control bfh-phone', 'data-country': 'UA', }),
        }
        labels = {
            'client_phone': _('Контактный номер'),
        }

Template with the bootstrap Modal form:

<div class="modal fade" id="offerModalForm" tabindex="-1" role="dialog"
             aria-labelledby="myModalLabel" aria-hidden="true">
            <div class="modal-dialog">
                <div class="modal-content">
                    <div class="modal-body">
                        <form role="form" action="ordercomplete" method="post" enctype="multipart/form-data">
                            {% csrf_token %}
                            {{ form }}
                            <div class="modal-footer">
                                <button type="submit" id="offerSubmitBtn" class="btn btn-primary" type="submit">
                                    Оформить заказ
                                </button>
                                <button type="button" class="btn btn-primary"
                                        data-dismiss="modal">
                                    Закрыть
                                </button>
                            </div>

                        </form>
                    </div>
                </div>
            </div>
        </div>

If I do like this:

def clean_client_phone(self):
        phone = self.cleaned_data.get('client_phone')
        if len(phone) < 13:
            raise forms.ValidationError(_('Invalid value'), code='invalid')
        return phone

Then form.isValid() become False and nothing happened.

Also here is my view:

def ordercomplete(request):
    if request.method == 'POST':
        form = OfferForm(request.POST, request.FILES)
        if form.is_valid():
            order = form.save()
            date = order.order_date.strftime('%d-%m-%Y %H:%M')
            phone = form.cleaned_data['client_phone']
        return render(request, 'viveska/ordercomplete.html')
    else:
        return render(request, 'viveska/ordercomplete.html')

html modal is a part of my main page, where I call it pushing button:

<button type="button" class="btn btn-lg make_order_btn" data-toggle="modal"
                            data-target="#offerModalForm">Оформить заказ
                    </button>

Update 1:

I edited ordercomplete view like this:

def ordercomplete(request):
    args = {}
    if request.method == 'POST':
        form = OfferForm(request.POST, request.FILES)
        logger.error(form.is_valid())
        if form.is_valid():
            order = form.save()
            return render(request, 'viveska/ordercomplete.html')
    else:
        form = OfferForm()
    phone_list = list(Phones.objects.all())
    logger.error(form.is_bound)
    args['form'] = form
    args['phone_list'] = phone_list
    return render(request, 'viveska/index.html', args)

and now it shows me field errors, but every time when some value is invalid it hides the form because it's modal. How can I kept it on screen after submit with invalid values?

bene25
  • 580
  • 6
  • 18
  • is the html the `ordercomplete` page? You never pass the form into the context so I'm not sure how the form even shows – Sayse Jan 26 '17 at 15:58
  • no, html is a part of my main page where I show modal with help of: ordercomplete.html only told that order being completed well. I've updated question. – bene25 Jan 26 '17 at 16:02
  • 1
    Basically you use {% if form.errors %} // your bootstrap modal logic here{% endif %} see this question http://stackoverflow.com/questions/22470637/django-show-validationerror-in-template – bhaskarc Jan 26 '17 at 16:02
  • you missed else condition for form.is_valid – RL Shyam Jan 26 '17 at 19:36
  • @tao suggestion helps, thanks:) but I need one more suggestion - see question Update 1. – bene25 Jan 26 '17 at 19:44

2 Answers2

0

You were 90% of the way there.

View:

    form_error = False
    if form.is_valid():
        order = form.save()
        date = order.order_date.strftime('%d-%m-%Y %H:%M')
        phone = form.cleaned_data['client_phone']
    else:
        form_error = True

Template:

    {% if form_error %}
        $(#offerModalForm).modal("show");
    {% endif %}

This will show the modal form to the user if there has been an error.

I believe JavaScript validation is likely still the way to go, as it does not result in any loading behavior and gives you the better formatted messages. The above solution will reload the page (which the user can visibly see) and then open the modal window (again, the user can see it).

The biggest advantage, that I can see, of having the form validation in the forms themselves is that you can have very consistent validation anywhere that the form is used without changing or adding any additional code.

Archetype90
  • 179
  • 1
  • 4
  • 19
  • Yes, main disadvantage of this method is that form will be reloaded. I agree form validation is really cool:) – bene25 Dec 02 '17 at 22:02
-1

Finally I did modal form validation via JavaScript. Thanks for answers.

Update 14/06/2022 Today I would go with HTMX instead of inventing custom validation with JS

bene25
  • 580
  • 6
  • 18