Django: Could not parse the remainder - javascript

I'm trying to pass a response from JsonResponse as a parameter of specific function in views. But, got the following error instead
django.template.exceptions.TemplateSyntaxError: Could not parse the remainder: '${response.id_ajuan}' from '${response.id_ajuan}'
Here it is my code
url.py
url(r'^course-eksternal/review/(?P<id>\d+)/update$', course_eksternal.update_ajuan, name='update-ajuan')
views.py
# Function that pass the JsonResponse
def get_update_ajuan(request):
ajuan = Pengajuan.objects.get(pk=request.POST.get('ajuan_id'))
res = {
'id_ajuan': ajuan.id,
...
}
status_code = 200
return JsonResponse(res, status=status_code)
file.html
# Get the JsonResponse
success : function(response) {
$('.modal-body').empty().append(`
<div class="modal-body">
<form action="{% url 'app:update-ajuan' id=${response.id_ajuan} %}" method="POST"> # Error occurs here
...
`);

Your success function is javascript that is running in the front-end. Django is not running your front-end and there is no processing of django templates going on here, so you can't use any django template tags.
What you will need to do is figure out what the url is in your view get_update_ajuan and then pass the whole url back.
from django.urls import reverse
def get_update_ajuan(request):
ajuan = Pengajuan.objects.get(pk=request.POST.get('ajuan_id'))
res = {
'id_ajuan': ajuan.id,
'action_url': reverse("app:update-ajuan", kwargs={"id": ajuan.id},
...
}
status_code = 200
return JsonResponse(res, status=status_code)
and then use that value:
success : function(response) {
$('.modal-body').empty().append(`
<div class="modal-body">
<form action="${response.action_url}" method="POST"> # Error occurs here
...
`);

Related

Django Ajax success send context in new url

I have a first page with a Launch button, the process is done and them all is redirect to a result page where I can download the different results. Without Ajax and with "regular" Django, the process is working. However, because of other functionalities in the first page, I have to work with Ajax. And if I do not redifined the success part of Ajax, nothing is appenning..
I have a function view for the first page :
def launchCtd(request):
"""
This Function is activate when user click on the launch button of the convertToDose page.
It receive the request, create the JSON file and launch the ConvertToDose Analysis. Then it redirect to the Result page
"""
if request.method == 'POST':
#DO stuff
context = {
'filename': img_out_path,
'protocol_file': json_pactrlRectth,
}
#return render(request, 'result.html', context)
return JsonResponse(context, safe=False)# I trie to pass the url but it was not a success...
else:
#Ini Forms
context = {
#Send Forms
}
return render(request, 'template.html', context)
the template of the first page (only ajax part)
$.ajax({
url: "",
type: "POST",
data: formData,
processData: false,
contentType: false,
beforeSend: function (xhr, settings) {
xhr.setRequestHeader("X-CSRFToken", $('input[name="csrfmiddlewaretoken"]').val());
},
success: function(data){
//print okay with JSONResponse in view
console.log(data.protocol_file)
//First try to send data in new url => undefined element, after = I tried with data and with template data in the 1st page
//protocol_file = $("input[name='json_path']")
//filename = $("input[name='img_path']")
//Second try to send data in new url => undefined
$('#protocol_file').html(data.protocol_file);
$('#filename').html(data.filename);
//Third try => GetElementById is undifined error
//document.GetElementById("protocol_file").innerHTML = $("input[name='json_path']")
//document.GetElementById("filename").innerHTML = $("input[name='img_path']")
//Fourth try => synthaxe error, I also tried with a + like in some forum but it consider like a str and concat all...
window.location.href="/filmchromique/result/" {data:data}
#this one is working but with no data sended ....
//window.location.href="/filmchromique/result/"
},
error: function (data, textStatus, jqXHR) {
console.log(data)
}
});
The view of the result page :
class displayResultPage(TemplateView):
template_name = 'result.html'
def post(self, request, *args, **kwargs):
self.object = self.get_object()
context = self.get_context_data(object=self.object)
return self.render_to_response(context)
def get_context_data(self, **kwargs):
kwargs = super(displayResultPage, self).get_context_data(**kwargs)
return kwargs
def post(self, request, *args, **kwargs):
context = self.get_context_data(**kwargs)
bar = self.request.POST.get('foo', None)
if bar: self.template_name = 'result.html'
return self.render_to_response(context)
In my template result, I have nothing particular, only maybe these part could be interesting :
<div style="padding-bottom: 30%" class="row gx-5 justify-content-center">
{% if protocol_file is not null %}
<p id="protocol_file">Your file is here : {{ filename }}</p>
{% else %}
<h1 style="color: indianred">You must launch an analysis before accessing an image on this page</h1>
{% endif %}
{% if protocol_file is not null %}
<div class="row gx-5 justify-content-center">
<div class="col-lg-4 col-xl-6">
<a class="btn btn-primary btn-md" href="{% url 'json:downloadFile' protocol_file %}">Save protocol to local</a>
</div>
<br>
<div class="col-lg-4 col-xl-6">
<a class="btn btn-primary btn-md" href="{% url 'json:downloadFile' filename %}">Save image to local</a>
</div>
<br>
</div>
I do not find a way to send the context. If you have any idea how I can do it please
Have a good day
EDIT
The problem seems not to be in the Ajax side but in the result view, here named displayResultPage. I used the debugger, and in the second post def, data are in the request (POST). So I had the idea to add them in the current context :
def post(self, request, *args, **kwargs):
context = self.get_context_data(**kwargs)
context["filename"] = self.request.POST.get("img_path")
context["protocol_file"] = self.request.POST.get("json_path")...
But the data are not displayed in the template.
When I use the debbugger, following the workflow :
the post function is called -> self.get_context_data called in the
post function -> return self.render_to_response of the post function
-> something done in class TemplateView -> come back in the get_context_data of displayResultPage -> something done in class
TemplatView -> page displayed
in the "come back in the get_context_data of displayResultPage" step, I do not find my data given to the context in the "the post function is called" step.
If you have any idea why, I think it is the solution here :) If I find a way I will post it.
Thanks

How to correctly use Fetch in JavaScript and Django?

I am trying to make a METAR decoder as shown:
I am using fetch in Vanilla js and I plan to send the entered code to a Django view. From the Django view, the decoded data will be taken and displayed in the template.
views.py
def ToolsPageView(request):
if request.method == "POST":
jsonData = json.loads(request.body)
metarCode = jsonData.get('Metar')
return JsonResponse("Success", safe=False)
return render(request, 'app/tools.html')
urls.py
...
path("tools", views.ToolsPageView, name="tools")
tools.html
<div class="metar-code-decode">
<form method="POST" action="{% url 'tools' %}" id="metar-form">
{% csrf_token %}
<input type="text" placeholder="Enter METAR: " id="metar-value"> <br>
<input type="submit" id="metar-button">
</form>
</div>
tool.js
function getDecodedMetar() {
let formButton = document.querySelector("#metar-button");
formButton.onclick = function (e) {
let metarCode = document.querySelector("#metar-value").value;
sendMetar(metarCode);
//e.preventDefault();
//getMetar(metarCode);
};
}
function sendMetar(metarCode) {
fetch('/tools', {
method: "POST",
headers: {
"X-CSRFToken": getCookie("csrftoken"),
},
body: JSON.stringify({
Metar: metarCode,
}),
});
}
I have used the same code for POST using fetch where I had to let user update his/her profile. And that worked. But, this does not work and the error keeps on changing from time to time after restarting the server. At the first try, there was no error produced and the server also showed a POST request being made. And the latest error which I am getting is "In order to allow non-dict objects to be serialized set the safe parameter to False." I get the same thing again and again even after setting safe=False within the JsonResponse(). Worth to note, request when converted to request.json() gives an error.
Am I using fetch wrongly? If yes, what is the correct way?
I'm not sure you have the flow right. The idea is that the button, when clicked, will call a function (fetch) that will send data to the view, which will decode it and send it back to the JavaScript, so that it could be displayed without reloading the entire page.
I think this might help:
let formButton = document.querySelector("#metar-button");
// When the button is clicked,
formButton.onclick = function(e) {
// do NOT send the form the usual way
e.preventDefault();
let metarCode = document.querySelector("#metar-value").value;
// Run the function that will send the code to the ToolsPageView
sendMetar(metarCode);
}
async function sendMetar(metarCode) {
const response = await fetch('/tools', {
method: "POST",
headers: {
"X-CSRFToken": getCookie("csrftoken"),
},
body: JSON.stringify({
'Metar': metarCode,
}),
})
.then(response => response.json())
.then(data => {
console.log(data);
// extract the decoded value from the data sent back from the view
// display it by targeting the element in your html that you want
// to display it
});
}
And in your view,
def ToolsPageView(request):
if request.method == "POST":
jsonData = json.loads(request.body)
metarCode = jsonData.get('Metar')
# Remove the original JsonResponse
# return JsonResponse("Success", safe=False)
# and INSTEAD,
# Send the code back to the JavaScript
# I don't THINK you need safe=False here?
return JsonResponse({'MetarCode': metarCode})
return render(request, 'app/tools.html')

returned json response is undefended django

I'm trying to load my json response into my template but when i check it into my console returns undefended !
#login_required
def booking_detail_lists(request,id):
obj = get_object_or_404(Booking.objects.annotate(no_persons=Count('takes_by')),id=id)
bookingvisitors = BookingVisitor.objects.filter(booking=obj)
doc = Document.objects.filter(booking=obj)
documents = []
for i in doc:
documents.append({
'source':i.docs.url
})
visitors = []
for i in bookingvisitors:
visitors.append({
'full_name':i.visitor.full_name,
'reason':i.reason,
'check_in_vis':i.check_in_vis.strftime("%Y-%m-%dT%H:%M"),
'check_out_vis':i.check_out_vis.strftime("%Y-%m-%dT%H:%M"),
'admin':i.admin.username,
'date':i.date.strftime("%Y-%m-%dT%H:%M")
})
data = {
'check_in':obj.check_in.strftime("%Y-%m-%dT%H:%M"),
'check_out':obj.check_out.strftime("%Y-%m-%dT%H:%M"),
'taker':obj.taker,
'phone':obj.phone,
'no_person':obj.no_persons,
'id':obj.id,
'takes_by':visitors,
'images':documents,
}
json_data = json.dumps(data)
return render(request,'booking/booking_detail.html',{'data':json_data,'obj':obj,'id':obj.id})
urls.py
path('ajax/booking/<int:id>',booking_detail_lists , name='booking_detail_lists'),
my html template and ajax
$.ajax({
type:'GET',
url:"{%url 'booking:booking_detail_lists' id=2222 %}".replace(/2222/,parseInt({{id}})),
success:function(data){
console.log(data.data)
}
})
<!--some html tags-->
but in the browser console returns undefinedbut when i just type {{data}} it show as i expected ?! thank you for your recommendation ..
in the function booking_detail_lists, you are returning render('<template_name>', {<Data for rendering in the template>})...
When you're calling this URL with ajax, actually the template booking_detail.html is returned, which is not in the json format, but the html one.. And this response doesn't have property data (which you're calling with data.data)..
JsonResponse
For the json response from django view, you need to use JsonResponse from django.http
Change your function to include this
# ...Rest Imports
from django.http import JsonResponse
#login_required
def booking_detail_lists(request, id):
# ...Processing and generation of data
return JsonResponse({'data':json_data,'obj':obj,'id':obj.id})

Flask server returning 400 error code from JS rest call

I'm calling my Flask view function (API) via Javascript (FETCH).
I'm having success with the GET method, but when using the PATCH method I'm receiving a 400 error code
(Failed to load resource: the server responded with a status of 400 (BAD REQUEST)).
I reviewed the url, seems ok and the ID is being passed as an integer, so no clue on why it's giving this error message.
This function (load_follow_link) is fetching via GET and updating my "Follow" to "Unfollow" tag (no errors here):
function load_follow_link(id) {
apply_csrf_token();
fetch(`/follow_unfollow/${id}`)
.then(response => response.json())
.then(data => {
if (data.is_following)
document.getElementById('follow-unfollow-btn').innerHTML = 'Unfollow';
else
document.getElementById('follow-unfollow-btn').innerHTML = 'Follow';
document.getElementById('followers-count').innerHTML = data.followers_count;
document.getElementById('following-count').innerHTML = data.following_count;
});
}
This is the PATCH function (follow_unfollow) triggering the error message. It is supposed to call the view function and update the DB:
function follow_unfollow(id) {
apply_csrf_token();
fetch(`/follow_unfollow/${id}`, {
method: 'PATCH'
})
.then(() => {
load_follow_link(id);
});
}
view function (doesn't get executed when request method is PATCH)
#app.route('/follow_unfollow/<int:tutor_id>', methods=['GET','PATCH'])
#login_required
def follow_unfollow(tutor_id):
""" GET: returns if user is following the tutor, followers and following total
PUT: follow or unfollow
"""
user = Users.query.get(current_user.id)
try:
tutor = Tutors.query.get(tutor_id)
except NoResultFound:
return JsonResponse({"error": "Tutor not registered"}, status=401)
following_count = user.following_total()
followers_count = tutor.followers_total()
is_following = user.is_following(tutor)
if request.method == 'GET':
return jsonify(is_following=is_following, followers_count=followers_count,
following_count=following_count)
elif request.method == 'PATCH':
if is_following:
user.unfollow(tutor)
else:
user.follow(tutor)
db.session.commit()
return success.return_response(message='Successfully Completed', status=204)
else:
return jsonify(error="GET or PUT request required", status=400)
I appreciate the help
Could be you are not returning a valid response. Where is success defined in success.return_response?
Why not just return jsonify(...)?

How to call a function in view by clicking a button in django?

I am trying to call the function ssl_verify from my html template . But it gives 404 error. Can anyone help me with this? Where i am wrong ?
#views.py
def ssl_verify( request , dns, port ):
if request.is_ajax():
result = dns + port
return result
#urls.py
url(r'ssl_verify/(\d+)/(\d+)/$', views.ssl_verify,name='ssl_verify'),
#script in html
function verify()
{
dns = document.getElementById("dns1").value;
port = document.getElementById("port1").value;
$.post('ssl_verify/'+dns+'/'+port+'/', function (data) {
alert (data) ;
});
}
Your urls.py must contain (replace the regexp line)
url(r'^ssl_verify/(?P<dns>[^/]+)/(?P<port>[^/]+)/$','views.check_ssl'),
or if you import:
from views import check_ssl
....
url(r'^ssl_verify/(?P<dns>[^/]+)/(?P<port>[^/]+)/$','check_ssl'),
and your views:
from django.http import HttpResponse
def check_ssl( request , dns, port ):
if request.is_ajax():
message = str(dns)+str(port)
return HttpResponse(message)
else:
return HttpResponse('/faulthandler') # declare in urls if needed

Categories

Resources