Sending Form Data via pure JavaScript:
- still in home.html
print form data in a loop:
<script>function handleTweetCreateFormDidSubmit(event) {event.preventDefault()const myForm = event.targetconst myFormData = new FormData(myForm)for(var myItem of myFormData.entries()){console.log(myItem)}//console.log(event)}//...</script>
to test, runserver and send something

in the console, we see “csrfmiddlewaretoken”, “next”, and “content”
also, the input text is still not updated into tweets.and also in home.html, test 2 other checkpoints
<script>function handleTweetCreateFormDidSubmit(event) {event.preventDefault()const myForm = event.targetconst myFormData = new FormData(myForm)const url = myForm.getAttribute("action")const method = myForm.getAttribute("method")console.log(url, method)}//...</script>
to test, runserver and send something

so
url = “/create-tweet”
method = “POST”Then, send form data as load_tweets() in home.html
<script>function handleTweetCreateFormDidSubmit(event) {event.preventDefault()const myForm = event.targetconst myFormData = new FormData(myForm)const url = myForm.getAttribute("action")const method = myForm.getAttribute("method")const xhr = new XMLHttpRequest()xhr.open(method, url)xhr.onload = function() {const serverResponse = xhr.responseconsole.log(serverResponse)}xhr.send(myFormData)}//...</script>
to test, runserver and send something:

This time we print the form data, and we see a complete HTML form format.
The form data is sent as a XMLHttpRequest()
Also, after we refresh the page:
…this time the content is created successfully.To make tweets page is reloaded in time, we apply loadTweets()
<script>function handleTweetCreateFormDidSubmit(event) {event.preventDefault()const myForm = event.targetconst myFormData = new FormData(myForm)const url = myForm.getAttribute("action")const method = myForm.getAttribute("method")const xhr = new XMLHttpRequest()xhr.open(method, url)xhr.onload = function() {const serverResponse = xhr.responseconsole.log(serverResponse)const tweetsEl = document.getElementById("tweets")loadTweets(tweetsEl)}xhr.send(myFormData)}//...</script>
Handling Ajax Requests
- Ajax stands for “Asynchronous JavaScript and XML”, it’s the current situation that we are handling
we add a checking step in /tweets/views.py to make sure is that request ajax
def tweet_create_view(request, *args, **kwargs):print("ajax", request.is_ajax()) # hereform = TweetForm(request.POST or None)print('post data is', request.POST)next_url = request.POST.get("next") or None# print('next_url', next_url)if form.is_valid():obj = form.save(commit=False)obj.save()if next_url != None and is_safe_url(next_url, ALLOWED_HOSTS):return redirect(next_url)form = TweetForm()return render(request, 'components/form.html', context={"form" : form})
to test, as usual runserver and send something:

and watch the console:ajax False
so it isn’t an ajax request.
HttpRequest.is_ajax() is actually looking for an ajax header
we can manually set the header in home.html
function handleTweetCreateFormDidSubmit(event) {event.preventDefault()const myForm = event.targetconst myFormData = new FormData(myForm)const url = myForm.getAttribute("action")const method = myForm.getAttribute("method")const xhr = new XMLHttpRequest()const responseType = "json"xhr.responseType = responseTypexhr.open(method, url)xhr.setRequestHeader("HTTP_X_REQUESTED_WITH", "XMLHttpRequest") //newxhr.setRequestHeader("X-Requested-With", "XMLHttpRequest") //newxhr.onload = function() {const serverResponse = xhr.responseconsole.log(serverResponse)const tweetsEl = document.getElementById("tweets")loadTweets(tweetsEl)}xhr.send(myFormData)}
to test, runserver and input

the console:ajax True
we use a 201 status for ajax requests in /tweets/views.py
def tweet_create_view(request, *args, **kwargs):# print("ajax", request.is_ajax())form = TweetForm(request.POST or None)print('post data is', request.POST)next_url = request.POST.get("next") or Noneif form.is_valid():obj = form.save(commit=False)obj.save()if request.is_ajax():return JsonResponse({}, status=201) # 201 == created itemsif next_url != None and is_safe_url(next_url, ALLOWED_HOSTS):return redirect(next_url)form = TweetForm()return render(request, 'components/form.html', context={"form" : form})
to test, runserver and input:

so there is no server response in console log this time.
Serialize Django Model Object:
we don’t need to pick individuals elements but a serialized data model to handle
- we write a serialize function in /tweets/models.py
- (still apply random “likes” for now) ```python from django.db import models import random # new
class Tweet(models.Model):
# id = models.AutoField(primary_key=True)content = models.TextField(blank=True, null=True)image = models.FileField(upload_to="images/", blank=True, null=True)def serialize(self): # newreturn {"id": self.id,"content": self.content,"likes": random.randint(0, 200)}
- then apply serialize() to /tweets/views.py```pythondef tweet_create_view(request, *args, **kwargs):form = TweetForm(request.POST or None)print('post data is', request.POST)next_url = request.POST.get("next") or Noneif form.is_valid():obj = form.save(commit=False)obj.save()if request.is_ajax():# return JsonResponse({}, status=201)return JsonResponse(obj.serialize(), status=201) # 201 == created itemsif next_url != None and is_safe_url(next_url, ALLOWED_HOSTS):return redirect(next_url)form = TweetForm()return render(request, 'components/form.html', context={"form" : form})# ...def tweet_list_view(request, *args, **kwargs):qs = Tweet.objects.all() # grab all objects in Tweet# tweets_list = [{"id" : x.id, "content" : x.content, "likes" : random.randint(0, 1000)} for x in qs]tweets_list = [x.serialize() for x in qs]data = {"isUser" : False,"response" : tweets_list}return JsonResponse(data)
to test, runserver and input
in the console, we get a serialized server response as our setting.
Rewrite the script part of home.html
<script>function handleTweetCreateFormDidSubmit(event) {//..xhr.onload = function() {if (xhr.status === 201) { //if that'sconst newTweetJson = xhr.responseconsole.log(newTweetJson.likes)const newTweetElement = formatTweetElement(newTweetJson)console.log(newTweetElement)tweetsContainerElement.prepend(newTweetElement) //prepend(add) newTweetElement before tweetsContainerElement}}xhr.send(myFormData)}//...//const tweetsEl = document.getElementById("tweets")const tweetsContainerElement = document.getElementById("tweets")//loadTweets(tweetsEl)loadTweets(tweetsContainerElement)//...</script>
to test, runserver

so “likes” is undefined right now, and “newTweetElement” is “formattedTweet” string in formatTweetElement()
but becasue loadTweets() also uses formatTweetElement() and lines under textarea includes “formattedTweet” string.
undefined should be a random number, I forgot 2 lines in handleTweetCreateFormDidSubmit()
