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' >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 %}
CodePudding user response:
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 !