form.errors is not returning bad request

Question:

Upon submitting a form, the desired outcome is to display validation error messages in the template if the form is not valid. When it comes to what I’m actually getting and the form doesn’t catch the errors (I have Max_length = 240… doesn’t catch an error when text is > 240).

forms.py:

from django import forms

from .models import Postit

MAX_POST_LENGTH = 240


class PostForm(forms.ModelForm):
    class Meta:
        model = Postit
        fields = ['content']

    def valid_content(self):
        content = self.validated_data.get("content")
        if len(content) > MAX_POST_LENGTH:
            raise forms.ValidationError("This message is too long")
        return content

views.py:

from django.http import HttpResponse, Http404, JsonResponse
from django.shortcuts import render, redirect
import random
from django.utils.http import url_has_allowed_host_and_scheme

from .forms import PostForm
from .models import Postit

# Create your views here.


def homepage_view(request, *args, **kwargs):
    return render(request, 'pages/home.html', context={}, status=200)

# create a new post and add to database


def post_create_view(request, *args, **kwargs):
    form = PostForm(request.POST or None)
    next_url = request.POST.get('next') or None  # pass next_url to respones
    if form.is_valid():
        obj = form.save(commit=False)
        obj.save()
        if request.headers.get('X-Requested-With' or
                               "HTTP_X_REQUESTED_WITH") == 'XMLHttpRequest':
            return JsonResponse(obj.serialize(),
                                status=201)  # testing if ajax is true
        if next_url is not None and url_has_allowed_host_and_scheme(next_url, 'localhost'):
            # if next_url invalid, no redirect - and check if safe
            return redirect(next_url)
        form = PostForm()
    if form.errors:
        if request.headers.get('X-Requested-With' or
                               "HTTP_X_REQUESTED_WITH") == 'XMLHttpRequest':
            return JsonResponse(form.errors, status=400)
    return render(request, 'comp/form.html', context={"form": form})


def postit_list_view(request, *args, **kwargs):
    """
    REST API VIEW
    return json data
    """
    query_set = Postit.objects.all()
    post_list = [x.serialize() for x in query_set]
    data = {
        "isUser": False,
        "response": post_list
    }
    return JsonResponse(data)


def postit_detail_view(request, postit_id, *args, **kwargs):
    """
    REST API VIEW
    return json data
    """
    data = {
        "id": postit_id,
    }
    status = 200
    try:
        obj = Postit.objects.get(id=postit_id)
        data['content'] = obj.content
    except:
        data['message'] = "Not found"
        status = 404
    return JsonResponse(data, status=status)
    # json.dumps content_type='application/json'

template view:

{% extends 'base.html' %}

{% block head_title %}
- now!
{% endblock head_title%}


{% block content %}

<div class='row text-center'>
    <div class='col'>
        <h1>Welcome to Shareit</h1>
    </div>
</div>

<div class='row mb-4'>
    <div class='col-10 col-md-4 mx-auto'>
        <form  class='form' id='create-post-form' method='POST' action='/create-post'>
            {% csrf_token %}
            <input type='hidden' value="/" name="next"/>
            <textarea required="required" class='form-control' name="content" placeholder="Post message here..."></textarea>
            <button type='submit' class="btn btn-primary">Post</button>
        </form>
    </div> 
</div>

<div class='row' id ='posts'>
    Loading...
</div>

<script>

function handleCreatePostFormDidSubmit(event) {
    event.preventDefault()
    const myForm = event.target
    const myFormData = new FormData(myForm)
    const url = myForm.getAttribute("action")
    const method = myForm.getAttribute("method")
    const xhr = new XMLHttpRequest()
    const responseType = "json"
    xhr.responseType = responseType
    xhr.open(method, url)
    xhr.setRequestHeader("HTTP_X_REQUESTED_WITH", "XMLHttpRequest")
    xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest")
    xhr.onload = function() {
        if (xhr.status === 201) {
            const newPostJson = xhr.response
            console.log(newPostJson.likes)
            const newPostElement = formatPostElement(newPostJson)
            console.log(newPostElement)
            const ogHtml = postElementContainer.innerHTML
            postElementContainer.innerHTML = newPostElement + ogHtml
            myForm.reset()
        }
        
    }
    xhr.send(myFormData)  
}

const createPostFormEl = document.getElementById("create-post-form")
createPostFormEl.addEventListener("submit", handleCreatePostFormDidSubmit)

const postElementContainer = document.getElementById("posts")

function loadPosts(postElement) {
    // dynamically receive the request 
    const xhr = new XMLHttpRequest()
    const method = 'GET' 
    const url = "/postit"
    const responseType = "json"
    xhr.responseType = responseType
    xhr.open(method, url)
    xhr.onload = function() {
        const serverResponse = xhr.response
        const listedItems = serverResponse.response // array of response
        var finalPostStr = ""
        var i;
        for (i=0; i<listedItems.length; i++) {
            var postObj = listedItems[i]
            var currentItem = formatPostElement(postObj)
                finalPostStr += currentItem
        }
        postElement.innerHTML = finalPostStr

    }
    xhr.send()
}

loadPosts(postElementContainer)


function handleLiked(post_id, currentCount) {
    console.log(post_id, currentCount)

}

function LikeBtn(post){ // like button that receives post id and number of likes
    return "<button class ='btn btn-primary btn-sm' onclick=handleLiked(" +
    post.id + ","+ post.likes + ")>" + post.likes +" Likes</button>"

}

function formatPostElement(post){

    var formattedPost = "<div class='col-12 col-md-10 mx-auto border py-3 mb-4' post id='post-" + post.id
    + "'><p>" + post.content +
        "</p><div class ='btn-group'>" + LikeBtn(post) +
        "</div></div>"
    return formattedPost
}

</script>
{% endblock content %}
Asked By: mpysys

||

Answers:

The clean_<fieldname>() method is called on a form subclass – where <fieldname> is replaced with the name of the form field attribute.

So in your case your need to use clean_content(self), this is not up to you.

If you have a title attribute then clean_title(self), you get the idea !

Answered By: Gaëtan GR
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.