I am trying to let the user select x and y coordinates from an image using cropper.js and pass the data with using ajax to the next view. I am using Django 1.9.4. I am also not really practiced with Javascript, the Javascript part is not written by me.
Using the Firefox Dev Tools Network Tab I seem to get a 500 Internal Server Error. In the Dev Tools view the request has the needed JSON data. However Django does not seem to work the request properly. Why?
Relevant part from views.py:
def render_stl(request):
print("Got to STL render")
if request.method == 'POST':
print("BELOW DATA")
print(request.POST) # <QueryDict: {}>
print(request.is_ajax()) # False
print(request.POST.__dict__) # {'_encoding': 'utf-8', '_mutable': False}
# This is old from a former version, but should be updated if ajax works
x_start = request.POST.get("x_start")
z_start = request.POST.get("z_start")
x_end = request.POST.get("x_end")
z_end = request.POST.get("z_end")
print(x_start, z_start, x_end, z_end)
run_stl_render(x_start, z_start, x_end, z_end)
# os.chdir(settings.MEDIA_ROOT)
stl_file = open(settings.MEDIA_ROOT + "/mySTL.stl", "r")
django_file = File(stl_file)
return render(request, 'img_crop/render_stl.html', {'django_file': django_file})
urls.py:
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^render_img$', views.upload_file, name='render_img'),
url(r'^render_stl$', views.render_stl, name='render_stl'),
url(r'^download_stl$', views.download_stl, name='download_stl'),
# url(r'^media/mySTL.stl', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT}),
]
Javascript (the csrftoken is defined in another function):
sendDataOfCroppedImage = function(dataOfCroppedImage) {
// var data = 'data : [' + JSON.stringify(dataOfCroppedImage) + ']';
var data_s = JSON.stringify(dataOfCroppedImage);
console.log('data',data_s);
$.ajax({
async: true,
crossDomain: true,
method: 'POST',
data: data_s,
dataType: 'json',
headers: {
'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest',
'content-type': 'application/json',
'cache-control': 'no-cache',
'X-CSRFToken': csrftoken
},
url: 'render_stl',
success: function () {
console.log('sendDataOfCroppedImage okay');
}
});
},
The template:
<html>
{% load staticfiles %}
<head>
<title>
Your rendered image
</title>
<script src="{% static 'img_crop/js/jquery-3.2.1.js' %}"></script>
<script src="{% static 'img_crop/js/cookie.js' %}"></script>
<script src="{% static 'img_crop/js/cropper.js' %}"></script>
<link href="{% static 'img_crop/css/cropper.css' %}" rel="stylesheet">
<style>
#image {
max-width: 100%;
}
</style>
</head>
<body>
<h1>Hier ist das generierte Bild aus Ihrer Welt!</h1>
<h2>Wählen Sie nun Ihren Bereich aus: </h2>
<div style="overflow: hidden; width: 400px; height: calc(400px / 16 * 9);">
<div>
<img id="image" src="{% static "img_crop/MC2px.png" %}" alt="Rendered image"/>
</div>
</div>
<button id="getDataBtn" class="button get-data">Submit Choice</button>
request.POST is only for form-encoded data. If you are sending json encoded data then you should access request.body instead.
data = json.loads(request.body.decode('utf-8'))
If you get a 500 error with DEBUG=True, then you should be able to see the traceback using your browser dev tools. If DEBUG=False, then look in your logs or the error email sent to the site admins.
Related
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!
I have madefunction that resends otp when the 'resend Otp' lick is clicked. This is django project. The following are the codes that I wrote.
html (this page extends base.html)
<a class="resend-otp" href="#" onclick="ReSendOTP('{{user.username}}', 'resendOTPmess')" ><i id="resendOTPmess">Resend</i>OTP?</a>
<script type="text/javascript" src="{% static 'jquery-3.6.0.min.js' %}"></script>
<script type="text/javascript" src="{% static 'regd_ajax.js' %}"></script>
js file
function ReSendOTP(username, mess_id){
mess = document.getElementById(mess_id);
mess.innerText = "Sending...";
$.ajax({
type: 'GET',
url: '/user/resendOTP',
data: {usr:username},
success: function(data){
mess.innerText = data;
}
})
}
views.py
def resend_otp(request):
if request.method == 'GET':
get_user = request.GET['usr']
if User.objects.filter(username = get_user).exists() and not User.objects.get(username = get_user).is_active:
user = User.objects.get(username=get_user)
user_otp = random.randint(100000, 999999)
UserOtp.objects.create(user = user, otp = user_otp)
mess = f"Hello, {user.first_name}, \nYour OTP is {user_otp}\n Thanks!"
send_mail(
"Welcome to Solve Litigation - Verify your Email", #subject
mess, #message
settings.EMAIL_HOST_USER, # sender
[user.email], #reciever
fail_silently= False
)
return HttpResponse("Resend")
return HttpResponse("Can't Send OTP")
urls.py
from .views import resend_otp
path('resendOTP', resend_otp)
So here I am requesting a resend otp for the "username: rick.bhardwaj27#gmail.com" but I am getting the follwing error in the console
jquery-3.6.0.min.js:2 GET http://127.0.0.1:8000/user/resendOTP?usr=rick.bhardwaj27%40gmail.com 404 (Not Found)
So i have got my html and i would like to add my django view in div "radio2".
I am using JQuery function Load() but i have a problem because it returns error 404 with get request "http://127.0.0.1:8000/post/afafa/%7B%" and its not loading nothing in div
post_detail.html
<div class="post__recommendation__posts">
<div id="radio2" class="radio2">
</div>
{% for post in posts|slice:":3" %}
<div class="post__recommendation__post">
<div class="post__recommendation__post-image">
<img src={% static post.image.url %} alt="shakhur" />
</div>
<div class="post__recommendation__post-description">{{post.short_description}}</div>
</div>
{% endfor %}
</div>
Js function
$(document).ready(function (){
console.log("Loading page")
$(".radio-btn").click(function(){
console.log("radio - btn")
console.log($(this)[0].id)
$.ajax({
url: "/radio/",
type: 'POST',
data:{
radio: "radio",
input: $(this)[0].id
},
success: update_item()
})
})
})
function update_item() {
$('#radio2').load(
"{% url 'radio2' %}"
);
}
View
#csrf_exempt
def radio_test(request):
return render(request, 'blogapp/radio2.html')
radio2.html
<div class="radiodiv">
This is Radio2
</div>
my results in console
Not Found: /post/afafa/{%
[28/Sep/2020 15:52:19] "GET /post/afafa/%7B% HTTP/1.1" 404 3938
[28/Sep/2020 15:52:19] "POST /radio/ HTTP/1.1" 200 79
[28/Sep/2020 15:52:22] "GET /post/afafa/ HTTP/1.1" 200 10761
It seems that you're trying to use Django's templating engine in a static file.
This will not work because static files are not passed into the templating engine.
There are work-arounds. Easiest is to create a global variable in the main template and pass that into load:
<script>
var radio2_url = "{% url 'radio2' %}";
</script>
Put this before your other script.
Then in your js:
function update_item() {
$('#radio2').load(radio2_url);
}
I am working on a django project in which I have gathered up all of my variables in js and am trying to initialize a form (inside a modal popup) on same page without any refresh. I have the form showing up inside my modal, but can't quite figure out the Ajax post method to get my js variables into the initial form fields. Any help would be much appreciated!
index.html - this function fires where I need it, but returns the page url instead of the data object I am trying to define.
Index.html
$.ajax({
method: "POST",
url: '',
data: {
geology: ('#geology').value,
latitude: ('latitude').value,
longitude: ('longitude').value,
csrfmiddlewaretoken: '{{ csrf_token }}',
},
success: function(data){
console.log(data.geology);
},
error: function(error_data){
console.log("error");
console.log(error_data);
}
});
views.py
def home_view(request):
geology = request.GET.get('geology')
latitude = request.GET.get('latitude')
longitude = request.GET.get('longitude')
form = MineralForm(initial={'mineral': mineral, 'geology': geology, 'latitude': latitude, 'longitude': "INITIAL", 'description': description}) # populates form with what user tried to submit...
UPDATE:
Here is an update on where I am at:
The modal window opens after an api call to gather some geology data. I am hoping to populate this form with the geology data, without refreshing the page. I am using ajax to create a post that get's my data object over to views.py (I am able to print the data upon POST from views.py into the terminal) but the form is not initializing with the data. Instead, it is initializing with the "PRE_POST" values, even after the api call to gather the data and post via ajax.
Any thoughts on what might be going on here, or how to resolve would be much appreciated!
matMap.html (snippets)
<!-- mineralForm Modal -->
<div class="modal fade draggable" id="mineralFormModal" role="dialog" style="height: 100%;">
<!-- Modal content-->
<div class="modal-header">
<button id ="mineralFormModalClose" type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title" align="center" style="font-family: Lobster">Add New Mineral</h4>
</div>
<div class="mineralFormModal_body" id="mineralFormModal_body" style="position:absolute; top:0">
<h3>loading before modal clears</h3>
</div>
<br>
{{ form }}
<br>
<button id="modalSave" type="button" class="btn btn-default" data-dismiss="modal">Save</button>
<div class="modal-footer red lighten-3">
<button id="modalClose" type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
(...)
$.ajax({
method: "POST",
url: '',
data: {
geology: geology,
latitude: x,
longitude: y,
csrfmiddlewaretoken: '{{ csrf_token }}',
},
success: function(data){
console.log("AJAX POST SUCCESS!"); //grabs this entire page and all variables.
},
error: function(error_data){
console.log("error");
console.log(error_data);
}
});
views.py
def home_view(request):
geology = request.POST.get('geology')
latitude = request.POST.get('latitude')
longitude = request.POST.get('longitude')
if request.method == "POST":
print("!!!! POSTING from HOME !!!!" + geology + " " + latitude + " " + longitude)
form = MineralForm(request.POST, initial={'geology': "POST_VALUE",'latitude': "POST_VALUE", 'longitude': "POST_VALUE"})
print("NOW WE ARE POSTING: ")
print(form)
return render(request, 'blog/matMap.html', {'form': form})
else:
print("LOADING HOME: INITIAL STATE (BEFORE POST)")
form = MineralForm(initial={'geology': "PRE_POST",'latitude': 'PRE_POST', 'longitude': 'PRE_POST'}) # populates form with what user tried to submit...
return render(request, 'blog/matMap.html', {'form': form})
And here is my terminal output, from initial page load through after the ajax post:
LOADING HOME: INITIAL STATE (BEFORE POST)
[13/Feb/2019 13:36:07] "GET / HTTP/1.1" 200 41261
Not Found: /js/scripts.js
[13/Feb/2019 13:36:07] "GET /js/scripts.js HTTP/1.1" 404 3210
Not Found: /js/scripts.js
[13/Feb/2019 13:36:08] "GET /js/scripts.js HTTP/1.1" 404 3210
[13/Feb/2019 13:36:08] "GET /api/chart/data/ HTTP/1.1" 200 4039
!!!! POSTING from HOME !!!!Miocene -119.48709 44.85346
NOW WE ARE POSTING:
<tr><th><label for="id_mineral">Mineral:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="mineral" required id="id_mineral"></td></tr>
<tr><th><label for="id_description">Description:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><textarea name="description" cols="40" rows="10" required id="id_description">
</textarea></td></tr>
<tr><th><label for="id_geology">Geology:</label></th><td><input type="text" name="geology" value="Miocene" required id="id_geology"></td></tr>
<tr><th><label for="id_latitude">Latitude:</label></th><td><input type="text" name="latitude" value="-119.48709" required id="id_latitude"></td></tr>
<tr><th><label for="id_longitude">Longitude:</label></th><td><input type="text" name="longitude" value="44.85346" required id="id_longitude"></td></tr>
[13/Feb/2019 13:36:30] "POST / HTTP/1.1" 200 41593
However, even after this, when I call up my modal form, it looks like this:
THANK YOU!!!
You're sending data via POST, so initialize your form with it:
form = MineralForm(request.POST or None)
You can not access your POST body data by request.GET use request.POST. And check this doc
def home_view(request):
geology = request.POST.get('geology')
latitude = request.POST.get('latitude')
longitude = request.POST.get('longitude')
form = MineralForm(initial={'mineral': mineral, 'geology': geology, 'latitude': latitude, 'longitude': "INITIAL", 'description': description}) # populates form with what user tried to submit...
i am working on for a basic feedback system. I just want to submit feedback with ajax, for example if fields are empty ajax will return some error msg and update the div at the same page with no redirection. if everything is ok it will update the feedbacks div with the new one...
Here is my code
models.py
from django.db import models
# Create your models here.
class FeedBack(models.Model):
title = models.CharField(max_length=255)
description = models.TextField()
def __unicode__(self):
return self.title
class Meta:
ordering = ["-title"]
views.py
import json
from django.shortcuts import *
from django.template import RequestContext
from submission.forms import *
def feedback(request):
if request.method == "POST":
form = FeedBackForm(request.POST)
message = 'Oops!'
if(form.is_valid()):
message = request.POST['title']
return HttpResponse(json.dumps({'message': message}))
return render_to_response('index.html',
{'form':FeedBackForm()}, RequestContext(request))
urls.py
from django.conf.urls import patterns, include, url
from submission.views import *
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
url(r'^admin/', include(admin.site.urls)),
url(r'^feedback/', feedback, name='feed_back'),
)
index.html
<html>
<head>
<script type="text/javascript" src="../static/helper.js"></script>
</head>
<body>
<h1>Leave a Suggestion Here</h1>
<div class="message"></div>
<div>
<form id="feed_form" action="" method="POST">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit Feedback" />
</form>
</div>
</body>
</html>
helper.js
$(document).ready(function() {
$('#feed_form').submit(function() { // catch the form's submit event
$.ajax({ // create an AJAX call...
data: $(this).serialize(), // get the form data
type: $(this).attr('method'), // GET or POST
url: '', // the file to call
success: function(data) { // on success..
$('.message').html(data); // update the DIV
},
error: function(e, x, r) { // on error..
$('.message').html(e); // update the DIV
}
});
return false;
});
});