Cache displays an unchecked checkbox as checked - javascript

I am building a simple todo list where you can create, check and delete todos.
All actions are implemented with AJAX logic so the page doesn't have to be reloaded all the time.
I get an error where an item that is checked=False is displayed as checked=True even though the data that is used to display the checkbox correctly says checked=False.
When the URL is called again instead of doing a refresh everything is displayed correctly which is why I suspect it to be a caching issue.
This process produces the error (all todos are unchecked):
Refresh page
Check first todo
Refresh page (First todo still correctly checked and data says checked=True).
Delete first todo.
Refresh page with ctr or cmd + R
-> Now the first item is correctly deleted but the former second todo is now checked even though it should be unchecked.
The data used to populate the template is also correct with checked=False.
This error does not happen when calling the URL again instead of cmd + R.
This is my index.html:
<html lang="en">
<head>
<meta http-equiv="cache-control" content="no-cache, no-store, must-revalidate">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Todo App</title>
<style>
.hidden {
display: none;
}
ul {
list-style: none;
padding: 0;
margin: 0;
}
</style>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">
</head>
<body>
<div class="container text-center">
<h2>Todo App</h2>
<div id="error" class="hidden">Something went wrong!</div>
<form id="form">
<input type="text" id="description" name="description" />
<input type="submit" value="Create" />
</form>
</div>
<ul id="todos" class="container">
{% for d in data %}
<li class="row" id="li_{{d.id}}">
{% print(d) %}
<div class="col text-end">
<input class="check-completed" type="checkbox" id={{d.id}}
{% if d.completed %}
checked
{% endif %}
/>
</div>
<label class="col text-center" for={{d.description}}>{{d.description}}</label>
<div class="col">
<button id="{{d.id}}" type="button" class="btn-close text-start" aria-label="Delete Todo item">
</button>
</div>
</li>
{% endfor %}
</ul>
<script type="text/javascript" src="{{ url_for('static', filename='todoScripts.js') }}"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.3.0-alpha1/dist/js/bootstrap.bundle.min.js" integrity="sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN" crossorigin="anonymous"></script>
</body>
</html>
This is the todoScripts.js file:
// New todo submit Script
document.getElementById('form').onsubmit = function(e) {
e.preventDefault();
fetch('/todo/create', {
method: 'POST',
body: JSON.stringify({
'description': document.getElementById('description').value,
}),
headers: {
'Content-Type': 'application/json',
}
})
.then(response => response.json())
.then(jsonResponse => {
console.log('response', jsonResponse);
data = jsonResponse
const liItem = createLiItem(data["id"], data["description"])
document.getElementById('todos').appendChild(liItem);
document.getElementById('error').className = 'hidden';
//reset form
const form = document.getElementById('form');
form.reset();
})
.catch(function() {
document.getElementById('error').className = '';
})
}
// Checkbox Script
const checkboxes = document.querySelectorAll('.check-completed');
for (let i = 0; i < checkboxes.length; i++) {
const checkbox = checkboxes[i];
checkbox.onchange = function(e) {
console.log('id:', e.target.id, 'is checked', e.target.checked);
fetch('/todo/set-completed', {
method: 'POST',
body: JSON.stringify({
'id': e.target.id,
'completed': e.target.checked
}),
headers: {
'Content-Type': 'application/json',
}
})
.then(response => {
console.log('response:', response);
document.getElementById('error').className = 'hidden';
})
.catch(function() {
document.getElementById('error').className = '';
})
}
}
// Delete script
const exes = document.querySelectorAll('.btn-close');
for (let i = 0; i < exes.length; i++) {
const ex = exes[i];
ex.onclick = function(e) {
close_id = e.explicitOriginalTarget.attributes.id.nodeValue
console.log('id:', close_id, 'shall be deleted');
fetch('/todo/delete', {
method: 'DELETE',
body: JSON.stringify({
'id': close_id,
}),
headers: {
'Content-Type': 'application/json',
}
})
.then(response => {
console.log('response:', response);
document.getElementById('li_'+close_id).remove(); //remove it from the DOM
document.getElementById('error').className = 'hidden';
})
.catch(function() {
document.getElementById('error').className = '';
})
}
}
And the app.py to run the server:
from flask import Flask, render_template, redirect, url_for, request, jsonify, abort
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
import sys
import pprint
app = Flask(__name__) # __name__ names the flask app after the file name (this case 'app')
app.config['SQLALCHEMY_DATABASE_URI'] = "postgresql://jj#localhost:5432/todoapp"
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
migrate = Migrate(app, db)
class Todo(db.Model):
id = db.Column(db.Integer, primary_key=True)
description = db.Column(db.String(), nullable=False)
completed = db.Column(db.Boolean(), nullable=False, default=False, server_default='true')
def __repr__(self) -> str:
return f"<Todo {self.id}, Done: {self.completed}, description: '{self.description[:20]}'"
#app.route('/')
def index():
todos_from_db = Todo.query.order_by('id').all()
pprint.pprint(todos_from_db)
return render_template('index.html', data=todos_from_db)
#app.route('/todo/create', methods=['POST'])
def create_todo():
error = False
try:
data = request.get_json()
description = data['description'] #get the description from the request body
new_todo = Todo(description=description)
db.session.add(new_todo)
db.session.commit()
except:
db.session.rollback()
error = True
print(sys.exc_info)
finally:
db.session.close()
if error:
abort(400)
else:
return jsonify({'description':description}
)
#app.route('/todo/set-completed', methods=['POST'])
def complete_todo():
error = False
try:
data = request.get_json()
todo = Todo.query.get(int(data['id']))
completed = data['completed']
todo.completed = completed
db.session.commit()
except:
db.session.rollback()
error = True
print(sys.exc_info)
finally:
db.session.close()
if error:
abort(400)
else:
return f"Updated todo with id {data['id']} to completed={data['completed']}"
#app.route("/todo/delete", methods=["DELETE"])
def delete_todo():
error = False
try:
id = int(request.get_json()["id"])
todo = Todo.query.get(id)
db.session.delete(todo)
db.session.commit()
except:
db.session.rollback()
error=True
print(sys.exc_info)
finally:
db.session.close()
if error:
abort(400)
else:
return f"Deleted {todo} with id {id}"
I tried forbidding to cache the page with the meta tag but atleast for firefox that didn't work.
Could someone point out my error or help me forbid caching? Thanks!

Related

JSON POST and GET 404 (Not Found)

I am trying to create an API in Django but am receiving the following errors message in the JavaScript console.
GET http://127.0.0.1:8000/edit/undefined 404 (Not Found)
POST http://127.0.0.1:8000/edit/undefined 404 (Not Found)
Does anyone know how to fix this problem?
API url: path("edit/<int:post_id>", views.edit, name="edit")
views.py
def edit(request, post_id):
try:
post = Post.objects.get(user=request.user, pk=post_id)
except Post.DoesNotExist:
return JsonResponse({"error": "Post does not exist."}, status=404)
if request.method == "GET":
return JsonResponse(post.serialize())
else:
return JsonResponse({"error": "Need a GET request."}, status=404)
JavaScript
document.addEventListener('DOMContentLoaded', function(){
const editButtons = document.querySelectorAll('.edit_button');
for (const button of editButtons) {
button.addEventListener('click', () => edit_email());
}
});
function edit_email(id){
console.log("edit button is clicked")
document.querySelector('#post_itself').style.display = 'none';
document.querySelector('#date_and_time').style.display = 'none';
document.querySelector('#likes').style.display = 'none';
const textarea = document.createElement('textarea');
//get post
fetch(`/edit/${id}`)
.then(response => response.json())
.then(post => {
textarea.innerHTML = `${post.post}`
document.querySelector('#p_user').append(textarea);
})
//save the post
fetch(`/edit/${id}`,{
method: 'POST',
post: JSON.stringify({
post: textarea.value
})
})
}
HTML
{% for post in page_obj.object_list %}
<div class = "individual_posts">
<h5 id="p_user" class = "post_user">{{ post.user }}</h5>
<h6 id = "post_itself">{{ post.post }}</h6>
<h6 id="date_and_time" class = "post_elements">{{ post.date_and_time }}</h6>
<h6 id="likes" class = "post_elements">{{ post.likes }}👍</h6>
{% if post.user == request.user %}
<button id="editButton" class="edit_button">Edit</button>
{% endif %}
</div>
{% endfor %}
I think something might be wrong in the way I am passing in the id to the API, but I am not sure. Could the for loop in the HTML be causing the problem?
models.py
class User(AbstractUser):
followers = models.ManyToManyField("self", related_name="users_followers", symmetrical=False)
following = models.ManyToManyField("self", related_name ="who_user_is_following", symmetrical=False)
def serialize(self):
return{
"followers": self.followers,
"following": self.following
}
class Post(models.Model):
post = models.TextField()
user = models.ForeignKey(User, on_delete=models.CASCADE, default="")
likes = models.IntegerField(default=0)
date_and_time = models.DateTimeField(auto_now_add=True)
def serialize(self):
return{
"id": self.id,
"post": self.post,
"user": self.user,
"likes": self.likes,
"date_and_time": self.date_and_time
}
you call edit_email without id here:
button.addEventListener('click', () => edit_email());
of cause, after call you get /edit/undefined on this line:
fetch(`/edit/${id}`)
you don't send anything like id, I can imagine it should be something like this:
button.addEventListener('click', (event) => edit_email(event.target.value));
You will also need to pass the value property to the button as post.id assuming that the post object will have an id key in your for loop.
If you are getting a reference error you need to check if page_obj.object_list has an id key for all the posts.

How to stop Getting 405 error Method not allowed?

I am trying to make my django project to work but somehow I always come to get this error
Method Not Allowed (POST): /
I have tried using decorators like #csrf_exempt like in the django documentation as to not encounter csrf errors and yet I came to this error.Please tell me what's the problem with my code...
urls.py
from test.views import HomePageView,predict
urlpatterns = [
path('', HomePageView.as_view(), name="homepage"),
path('predict', predict, name="predict"),]
views.py
class HomePageView(Notif, TemplateView):
template_name = "homepage.html"
def predict(self, request, *args, **kwargs):
if request == 'POST':
text = self.request.get_json().get('message')
# check if text is valid
response = get_response(text)
message = {'answer': response}
return JsonResponse(message)
#method_decorator(csrf_exempt)
def dispatch(self, *args, **kwargs):
return super(HomePageView, self).dispatch(*args, **kwargs)
app.js
onSendButton(chatbox) {
var textField = chatbox.querySelector('input');
let text1 = textField.value
if (text1 === "") {
return;
}
let msg1 = { name: "User", message: text1 }
this.messages.push(msg1);
fetch( $SCRIPT_ROOT+'/predict',{
method: 'POST',
body: JSON.stringify({ message: text1 }),
mode: 'same-origin',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'X-CSRFToken':csrftoken,
},
})
.then(r => r.json())
.then(r => {
let msg2 = { name: "Sam", message: r.answer };
this.messages.push(msg2);
this.updateChatText(chatbox)
textField.value = ''
}).catch((error) => {
console.error('Error:', error);
this.updateChatText(chatbox)
textField.value = ''
});
}
homepage.html
<div class="container">
{% csrf_token %}
<div class="chatbox">
<div class="chatbox__support">
<div class="chatbox__header">
<div class="chatbox__image--header">
<img src="https://img.icons8.com/color/48/000000/circled-user-female-skin-type-5--v1.png" alt="image">
</div>
<div class="chatbox__content--header">
<h4 class="chatbox__heading--header">Chat support</h4>
<p class="chatbox__description--header">Hi. My name is Sam. How can I help you?</p>
</div>
</div>
<div class="chatbox__messages">
<div></div>
</div>
<div class="chatbox__footer">
<input type="text" placeholder="Write a message...">
<button class="chatbox__send--footer send__button">Send</button>
</div>
</div>
<div class="chatbox__button">
<button class="btn-light"><img src="./images/chatbox-icon.svg" width="45px" height="45px"/></button>
</div>
</div>
</div>
<script type="text/javascript">
$SCRIPT_ROOT='{{ request.path }}'
</script>
Method Not Allowed (POST): / - means your function is not accepting post methos it accpets only get or other safe methods.
you're not changing any state of your database so you don't have to use post request you can use get intead of post
class HomePageView(Notif, TemplateView):
template_name = "homepage.html"
#staticmethod
def predict(self, request, *args, **kwargs):
if request == "POST":
text = self.request.get_json().get("message")
# check if text is valid
response = get_response(text)
message = {"answer": response}
return JsonResponse(message)
#method_decorator(csrf_exempt)
def dispatch(self, *args, **kwargs):
return super(HomePageView, self).dispatch(*args, **kwargs)
and change your urls like this
urlpatterns = [
path('predict', HomePageView.predict, name="predict"),
]
and in your javascript change method post to get
fetch($SCRIPT_ROOT + '/predict', {
method: 'GET',
body: JSON.stringify({
message: text1
}),
mode: 'same-origin',
})

Blocked by CORS policy No 'Access-Control-Allow-Origin' header is present on the requested resource

I'm currently making a project to put up "Post" from mysql onto a website and then they can also be updated from the website into Mysql. My insert function works fine because I can add post like nothing. Whenever I try and delete a post it gives me a long CORS policy error. I've looked all over the internet for an answer, but haven't found a solution. I've tried installing the CORS extensions in chrome and to also change the header into no cors. I'm the owner of the API being used.
index.js
const baseUrl = "**redacted for security**"
//const baseUrl = "https://localhost:5001/api/post"
//update
function getPost(){
//const allPostsApi = "https://localhost:5001/api/post";
const allPostsApi = baseUrl;
fetch(allPostsApi).then(function(response){
console.log(response);
return response.json();
}).then(function(json){
let html = "<ul>";
json.forEach((post)=>{
html += "<li>" + post.text + " Posted by Big Al! </li>";
})
html += "</ul>";
document.getElementById("Post").innerHTML = html;
}).catch(function(error){
console.log(error);
});
}
function handleOnSubmit(){
console.log("We made it");
var postText = document.getElementById("text").value;
//const placeHolder = document.getElementById("Nothing").value;
//const addPostsApi = "https://localhost:5001/api/post";
console.log(postText);
const addPostsApi = baseUrl;
var text ={
Text: postText
}
PlacePost(text);
}
function handleOnEnter(){
console.log("We made it");
var postId = document.getElementById("id").value;
//const placeHolder = document.getElementById("Nothing").value;
//const addPostsApi = "https://localhost:5001/api/post";
console.log(postId);
const addPostsApi = baseUrl;
var id ={
Text: postId
}
RemovePost(postId);
}
function PlacePost(text){
const PlacePostUrl = baseUrl;
fetch(PlacePostUrl, {
method: "POST",
headers: {
"Accept": 'application/json',
"Content-Type": 'application/json'
},
body: JSON.stringify(text)
}).then(response=>{
getPost();
})
}
function RemovePost(id){
const RemovePostUrl = baseUrl;
fetch(RemovePostUrl, {
mode: 'cors',
method: "PUT",
headers: {
"Accept":'application/json',
"Content-Type": 'application/json; charset=UTF-8'
},
body: JSON.stringify(id)
}).then(response=>{
getPost();
})
}
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<link href="resources/index.css" rel="stylesheet">
<title>Document</title>
</head>
<body onload = "getPost()">
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
<script type = "text/javascript" src = "scripts/index.js"></script>
<div id="Post">
</div>
<div class = "row">
<form id = "addPost" onsumbit ="return false;" method = "post">
<label for="title">Enter Post</label>
<input type ="text" name = "text" id ="text">
<input type ="button" value = "Submit" onclick="handleOnSubmit()">
</form>
<form id = "RemovePost" onsubmit ="return false;" method = "put">
<label for ="title">Enter Post Number you wish to delete</label>
<input type ="text" name = "text" id ="id">
<input type ="button" value = "Submit" onclick="handleOnEnter()">
</form>
</div>
</body>
</html>
I'm just very confused on how it does through on the PlacePost, but gets caught up during RemovePost. Any and all help is appreciated.
Remove mode: 'cors' from your RemovePostUrl fetch.
You could set it to same-origin if your js is running on the same domain as your API.
https://developer.mozilla.org/en-US/docs/Web/API/Request/mode
You 100% do not need a browser extension.
install 'cors' by using 'npm i cors'
const express = require("express");
const app = express();
const cors = require("cors");
app.use(
cors({
origin: "*"
}
));
cors does not care about requests between the same origin. If you want to allow request from an within the same origin then you can set the origin value to the URL you want to request. e.g
origin: 'http://127.0.0.1:8000'
And if you want to just allow all URLs to access your site you can instead use origin: '*' in the header and that will allow cross origin requests from any URL
Hope this helps :)

Django form JSON

Please tell me where the problem is:
I need to process a JSON request, what should I access and what should I return? and this is the essence of the problem, because the answer comes to me on the server, that there is a problem with the token.
contact.html:
<form class="feedback__form" id="contact_form" role="form" action="{% url 'contact' %}" method="post">
{% csrf_token %}
<div class="feedback__inv-msg feedback__response-msg">
<span> ERROR</span>
</div>
<div class="feedback__form-wrapper">
<ul class="feedback__field-list">
<li class="feedback__field-item">
<div class="feedback__field-title txt txt_font_mp_regular txt_size_18"><span>YOUR NAME</span></div>
<div class="feedback__field-inp">
{{ contact_form.contact_name }}
</div>
</li>
<li class="feedback__field-item">
<div class="feedback__field-title txt txt_font_mp_regular txt_size_18"><span>YOUR MAIL</span></div>
<div class="feedback__field-inp">
{{ contact_form.contact_email }}
</div>
<li class="feedback__field-item">
<div class="feedback__field-title txt txt_font_mp_regular txt_size_18"><span>YOUR PHONE</span></div>
<div class="feedback__field-inp">
{{ contact_form.contact_phone }}
</div>
<li class="feedback__field-item">
<div class="feedback__field-title txt txt_font_mp_regular txt_size_18"><span>YOUR PROBLEM</span></div>
<div class="feedback__field-inp">
{{ contact_form.content }}
</div>
</li>
<div class="feedback__controls">
<button class="btn btn_compact feedback__sender" type="submit">SEND</button>
</div>
<div class="feedback__response">
<div class="feedback__positive feedback__response-msg"><span>YOUR MESSAGE WAS SENT</span></div>
<div class="feedback__negative feedback__response-msg"><span>YOUR MESSAGE WASNT SENT</span></div>
</div>
</form>
<script type="text/javascript">
class Form {
constructor(){
this.element = document.querySelector(`.feedback`)
this.init()
this.isValid = false
this.values = {}
}
addClassesToImps(){
for(let elem of this.element.querySelectorAll(`input`))
elem.classList.add(`inp`)
this.element.querySelector(`input[type="hidden"]`).classList.remove(`inp`)
}
getStructure(){
this.addClassesToImps()
this.form = this.element.querySelector(`.feedback__form`)
this.inps = this.element.querySelectorAll(`.inp`)
this.reqInps = this.element.querySelectorAll(`.inp[required]`)
this.sender = this.element.querySelector(`.feedback__sender`)
}
handleValidityCheck(elem){
if(!elem.checkValidity()){
elem.classList.add(`inp_invalid`)
this.isValid = false
} else {
elem.classList.remove(`inp_invalid`)
elem.classList.add(`inp_valid`)
}
}
handleSenderClick(e){
e.preventDefault()
this.isValid = true
for(let elem of this.reqInps){
this.handleValidityCheck(elem)
}
if(this.isValid){
this.element.classList.remove(`feedback_inv`)
this.values.name = this.element.querySelector(`.inp[name="contact_name"]`).value
this.values.mail = this.element.querySelector(`.inp[name="contact_email"]`).value
this.values.phone = this.element.querySelector(`.inp[name="contact_phone"]`).value
this.values.text = this.element.querySelector(`.inp[name="content"]`).value
async function postData(url = '', data = {}) {
const response = await fetch(url, {
method: 'POST', // *GET, POST, PUT, DELETE, etc.
mode: 'cors', // no-cors, *cors, same-origin
cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
credentials: 'same-origin', // include, *same-origin, omit
headers: {
'Content-Type': 'application/json'
// 'Content-Type': 'application/x-www-form-urlencoded',
},
redirect: 'follow', // manual, *follow, error
referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
body: JSON.stringify(data) // body data type must match "Content-Type" header
});
return response.json(); // parses JSON response into native JavaScript objects
}
postData(``, this.values)
.then(data => {
console.log(data); // JSON data parsed by `response.json()` call
});
} else {
this.element.classList.add(`feedback_inv`)
return false
}
}
init(){
this.getStructure()
console.log(this)
this.sender.addEventListener(`click`, this.handleSenderClick.bind(this))
for(let elem of this.inps){
elem.addEventListener(`focusout`, this.handleValidityCheck.bind(this, elem))
}
}
}
let feedback = new Form()
</script>
forms.py:
class ContactForm(forms.Form):
contact_name = forms.CharField(required=True)
contact_email = forms.EmailField(required=True)
contact_phone = forms.CharField(required=False)
content = forms.CharField(
required=True,
widget=forms.Textarea(attrs={'id': 'my_field', 'class': 'feedback__textarea inp'})
)
# the new bit we're adding
def __init__(self, *args, **kwargs):
super(ContactForm, self).__init__(*args, **kwargs)
self.fields['contact_name'].label = "Name:"
self.fields['contact_email'].label = "Mail:"
self.fields['contact_phone'].label = "Phone"
self.fields['content'].label = "Your problem"
views.py:
def contact(request):
form_class = ContactForm
if request.method == 'POST':
form = form_class(data=request.POST)
if form.is_valid():
contact_name = request.POST.get(
'contact_name'
, '')
contact_phone = request.POST.get(
'contact_phone'
, '')
contact_email = request.POST.get(
'contact_email'
, '')
form_content = request.POST.get('content', '')
# Email the profile with the
# contact information
template = get_template('contact_template.txt')
context = {
'contact_name': contact_name,
'contact_email': contact_email,
'contact_phone': contact_phone,
'form_content': form_content,
}
content = template.render(context)
email = EmailMessage(
"New message from form",
content,
'', ['mail#mail.com'],
headers = {'Reply-To': contact_email }
)
email.send()
return HttpResponse('')
in urls.py:
...
path('contact/', views.contact, name='contact'),
...
in server console:
Forbidden (CSRF token missing or incorrect.)
"POST / HTTP/1.1" 403
in browser console:
SyntaxError: JSON.parse: unexpected character at line 2 column 1 of the JSON data
Please do not recommend options using jQuery, its presence is excluded in this project
In your script take the csrf token value using the below line
var token = jQuery("[name=csrfmiddlewaretoken]").val();
and when you sending data to server use one more parameter
headers: {'X-CSRFToken': token}
It will resolve your csrf error and make sure in form you have defined {% csrf_token %}.

AJAX in Django rendering JSON

I am trying to pass a JSON object to a view. This view will print out the JSON object in a template. This is just a test to see what data I am passing in Django.
Before the JSON object gets sent, I have javascript that will validate the data being sent. If the validation passes then the data is sent via AJAX.
I currently cannot get anything to be sent to the desired view. I am getting a 403 for the POST.
[22/Dec/2014 21:36:52] "POST /test/ HTTP/1.1" 403 2295
Here is the gist of my code: https://gist.github.com/liondancer/a9df593daeeecce7f180
JS:
$(document).ready(function() {
// Data to describe what kind of test
var testData = {
"timestamp": "",
"hive": 0,
"hdfs": 0,
// Contains a list of testData objects
"beacons":[]
};
var testRun = document.getElementById("test-form");
testRun.addEventListener('submit', function(event) {
event.preventDefault();
var selectedTest = document.querySelector('input[name=test-select]:checked');
alert(selectedTest);
var testType = selectedTest.id;
if (testType == "hdfs-test") {
testData["hdfs"] = 1;
testData["hive"] = 0;
} else if (testType == "hive-test") {
testData["hdfs"] = 0;
testData["hive"] = 1;
} else if (testType == "hdfs-hive-test") {
testData["hdfs"] = 1;
testData["hive"] = 1;
} else {
// null
}
var events = document.getElementById("event-textarea").value;
// check in valid input
var eventSource = events.replace("],[","],,,,[");
// beaconLists allows users to submit --> [{beacon1}, {beacon2}, ...], [{beacon3}, {beacon4}, ...]
var beaconLists = eventSource.split(",,,,");
for (var i = 0; i < beaconLists.length; i++) {
// inspect one list in beaconLists [{beacon1}, {beacon2}, ...]
var beaconList = beaconLists[i];
try {
// list of JSON objects
var beaconObjList = JSON.parse(beaconList);
for (var j = 0; j < beaconObjList.length; j++) {
var beaconObj = beaconObjList[j];
if (beaconObj["data"] && beaconObj["application"]) {
// successful parse to find events
// describe beacon being tested
alert("yes");
var beacon = {
"app_name": beaconObj["application"]["app_name"],
"device": beaconObj["application"]["device"],
"device_id": beaconObj["application"]["device_id"],
"os": beaconObj["application"]["os"],
"os_version": beaconObj["application"]["os_version"],
"browser": beaconObj["application"]["browser"],
"beacon": beaconObj
};
// append to testData
testData["beacons"].push(beacon);
// reset beacon so we can append new beacon later
beacon = {};
} else {
// notify event isn't in the correct format?
alert("no");
}
}
} catch (e) {
// notify bad JSON
alert("failed");
}
}
console.log(testData);
//$.ajaxSetup({
// beforeSend: function(xhr, settings) {
// if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
// xhr.setRequestHeader("X-CSRFToken", csrftoken);
// }
// }
//});
$.ajax({
type: "POST",
url: "/test/",
data: testData,
success: function () {
alert("yay");
},
failure: function () {
alert("boo");
}
});
});
});
html:
{% extends 'index/index.html' %}
{% load staticfiles %}
{% block head %}
<script type="text/javascript" src="{{ STATIC_URL }}home/js/home.js" async></script>
<link href="{{ STATIC_URL }}home/css/home.css" rel="stylesheet">
{% endblock head %}
{% block content %}
<div>Welcome to Trinity E2E testing</div>
<form id="test-form">
{% csrf_token %}
<input id="hdfs-test" type="radio" name="test-select" class="btn btn-default btn-lg">HDFS
<input id="hive-test" type="radio" name="test-select" class="btn btn-default btn-lg">HIVE
<input id="hdfs-hive-test" type="radio" name="test-select" class="btn btn-default btn-lg">BOTH
<textarea id="event-textarea" rows="8" class="form-control" placeholder="Events..."></textarea>
<input id="submit-test" type="submit" class="btn btn-default btn-lg" value="Submit">
</form>
{% endblock content %}
home/views.py:
from django.shortcuts import render
def load_homepage(request):
return render(request, 'home/home_page.html', '')
def scan_events(request):
if request == "POST":
# json = request.POST['testData']
# condition statement for file upload ot c/p events
return render(request, 'home/test.html', {'data': request.POST})
test.html:
{{ data }}
urls.py:
urlpatterns = patterns('',
url(r'^admin/', include(admin.site.urls)),
url(r'parser/', include("parser.urls", namespace="parser")),
url(r'^$', 'home.views.load_homepage', name='home'),
# url(r'form_data', 'parser.views.form_handler', name='')
url(r'test/$', 'home.views.scan_events'),
)
try to send CSRF token
$.ajax({
type: "POST",
url: "/test/",
data: {
csrfmiddlewaretoken: document.getElementsByName('csrfmiddlewaretoken')[0].value, testData,
},
success: function () {
alert("yay");
},
failure: function () {
alert("boo");
}
});

Categories