Aditya
Aditya

Reputation: 85

Issue in form validation

I want to validate my update form using form validation. When i leave a field blank and hit update button I get a blank page showing the error message. I want that error message to be displayed on top of that particular field when I leave it blank and hit update button.

This is my latest update view:

def update(request, id):
    item = get_object_or_404(BookEntry, id=id)
    if request.method == "POST":
        form = UpdateForm(request.POST, instance=item)
        # print template
        error_messages = {
            'error': form.errors,
        }
        if form.is_valid():
            print(form.cleaned_data)
            post = form.save(commit=False)
            post.save()
            return HttpResponseRedirect(reverse('bms:index'), id)
        else:
            form = UpdateForm()
            return HttpResponse(json.dumps(error_messages))
    return render(request, 'index.html',{'form':form})

This is my old update view:

def update(request, id):
    item = get_object_or_404(BookEntry, id=id)
    if request.method=="POST":
        form = UpdateForm(request.POST, instance=item)
        if form.is_valid():
            post=form.save(commit=False)
            post.save()
            return HttpResponseRedirect(reverse('bms:index'), id)
        else:
            form=UpdateForm(instance=item)
            return HttpResponseRedirect(reverse('bms:index'), id)
        return render(request, 'bms.html',{'form':form})

This is my forms.py:

class UpdateForm(forms.ModelForm):
    title = forms.CharField(max_length=100)
    author = forms.CharField(max_length=100)
    edition = forms.CharField(max_length=100)
    publisher = forms.CharField(max_length=100)
    genre = forms.CharField(max_length=100)
    detail = forms.CharField(max_length=100)
    language = forms.CharField(max_length=100)
    price = forms.IntegerField()
    dop = forms.CharField(max_length=100)
    cop = forms.CharField(max_length=100)
    copyright = forms.CharField(max_length=100)
    isbn = forms.IntegerField()

    class Meta:
        model = BookEntry
        fields = '__all__'

This is my html form:

<form action="{% url 'bms:update' book.id %}" id="updateform" name="updateform" method="POST">
  {% csrf_token%}
  <div class = "form-group">
    <label for = "title">
      Title:
    </label>
    <input class = "form-control" id="book_title" type = "text" name="title" value="{{ book.title }}">
  </div>
  <div class="form-group">
    <label for = "author">
      Author:
    </label>
    <input id="book_author" class = 'form-control' type = "text" name="author" value="{{ book.author }}">
  </div>
  <div class = "form-group">
    <label for = "edition">
      Edition:
    </label>
    <input id="book_edition" type = "text" class = 'form-control' name="edition" value="{{ book.edition }}">
  </div>
  <div class = "form-group">
    <label for ="publisher">
      Publisher:
    </label>
    <input id="book_publisher" type = "text" name="publisher" class = 'form-control' value="{{ book.publisher }}"/>
  </div>
  <div class = "form-group">
    <label for ="genre">
      Genre:
    </label>
    <input id="book_genre" type = "text" name="genre" class = 'form-control' value="{{ book.genre }}"/>
  </div>
  <div class = "form-group">
    <label for ="detail">
      Detail:
    </label>
    <input id="book_detail" type = "text" name="detail" class = 'form-control' value="{{ book.detail }}"/>
  </div>
  <div class = "form-group">
    <label for ="language">
      Language:
    </label>
    <input id="book_language" type = "text" name="language" class = 'form-control' value="{{ book.language }}"/>
  </div>
  <div class = "form-group">
    <label for ="price">
      Price:
    </label>
    <input id="book_price" type = "text" name="price" class = 'form-control' value="{{ book.price }}"/>
  </div>
  <div class = "form-group">
    <label for ="dop">
      DOP:
    </label>
    <input id="book_dop" type = "text" name="dop" class = 'form-control' value="{{ book.dop }}"/>
  </div>
  <div class = "form-group">
    <label for ="cop">
      COP:
    </label>
    <input id="book_cop" type = "text" name="cop" class = 'form-control' value="{{ book.cop }}"/>
  </div>
  <div class = "form-group">
    <label for ="cop">
      Copyright
    </label>
    <input id="book_copyright" type = "text" name="copyright" class = 'form-control' value="{{ book.copyright }}"/>
  </div>
  <div class = "form-group">
    <label for ="isbn">
      ISBN:
    </label>
    <input id="book_isbn" type = "text" name="isbn" class = 'form-control' value="{{ book.isbn }}"/>
  </div>
  <input type = "submit" value="Update" id="update" class = "btn btn-success" style="font-size:18px;" />
</form>

This is the URL it shows when a field is left empty:

http://127.0.0.1:8000/bms/update/2/

And this is the error message:

{"error": {"edition": ["This field is required."]}}

I had left edition field empty to check if validation is working properly or not.

Can anyone suggest me how to do it the right way?

Upvotes: 0

Views: 43

Answers (1)

rtindru
rtindru

Reputation: 5337

As Daniel pointed out, you need to re-render the form.

The basics of HTTP Form Post are: If the form is valid: save + do a HttpResponseRedirect If the form is not valid; re-render the same template with the errors

Change your function to:

def update(request, id):
    item = get_object_or_404(BookEntry, id=id)
    if request.method == "POST":
        form = UpdateForm(request.POST, instance=item)
        # print template
        error_messages = {
            'error': form.errors,
        }
        if form.is_valid():
            print(form.cleaned_data)
            post = form.save(commit=False)
            post.save()
            return HttpResponseRedirect(reverse('bms:index'), id)
        return render(request, 'index.html',{'form':form})  # Form invalid case is handled here; the form is reused from above; form.errors is available in the template now
    else:
        pass # Handle GET requests here

Upvotes: 1

Related Questions