Error trying to save data in django via ajax(fetch) - python

I have a model that references other models, I am trying to save data using ajax
Example:
class Friend(models.Model):
name = ...
class Main(models.Model):
name = ....
friend = models.ForeignKey(Friend, on_delete=models.CASCADE)
All body comes from ajax(fetch) request
I have a table (html), and add data to cells, then with the
enter event, send data.
Like this:
input.addEventListener("keyup", function (e) {
//in this scenario I already have the whole row
// get full_row `row_data`
post_ajax = {
method: "POST",
headers: {
"X-CSRFToken": crf_token, // I get it with a regular expression
"Content-Type": "application/json",
"X-Requested-With": "XMLHttpRequest",
Accept: "application/json",
},
body: JSON.stringify(row_data),
};
fetch("my_url", post_ajax)
.then((res) => res.json())
.catch((error) => console.error("Error:", error))
.then((response) => console.log("Success:", response));
});
My view function
def save_post(request):
if request.is_ajax and request.method == "POST":
body_unicode = request.body.decode('utf-8')
data = json.loads(body_unicode)
print('here the data arrives',data)
# here the data arrives {'name': 'Ale', 'friend_id': 22}
Main.objects.create(name=data['name'], friends=data['friend_id'])
return JsonResponse({"instance": data}, status=200)
return JsonResponse({"error": ""}, status=400)
This is the error
raise TypeError("%s() got an unexpected keyword argument '%s'" %
(cls.__name__, kwarg))
TypeError: Main() got an unexpected keyword argument 'Friends'
Any idea or suggestion?

EDIT:
When you are creating the Main object, try making the "friend" attribute an object, like this:
friend = Friend.objects.get(id=data['friend_id'])
Main.objects.create(name=data['name'], friend=friend)
Also, the main issue appears to be you are calling the column "friends" but it should be "friend" when you are creating the Main object.
This:
Main.objects.create(name=data['name'], friends=data['friend_id'])
Should be:
Main.objects.create(name=data['name'], friend=data['friend_id'])
PREVIOUS ANSWER:
Assuming you are using JQuery in the template to send an AJAX request, since you did not specify.
In your urls.py:
...
path('/api/post_friend/', post_friend_api, name="post_friend_api"),
...
In your template :
<script type="text/javascript">
$("#myBurron").click(function(){
var csrfToken = $( "input[name='csrfmiddlewaretoken']"); // assuming this is a form
var friend_name = $("#friend_name").val();
$.ajax({ url: '{% url 'post_friend_api' %}',
type: "POST",
dataType: "json",
data: {'friend':friend_name, 'csrfmiddlewaretoken':csrfToken.val()},
cache: false
}).done(function(data) {
if (data.result === true){
alert(data.message);
}
});
});
});
</script>
In your views.py:
from django.http import JsonResponse
def post_friend_api(request):
data = {}
if request.POST.get('friend', None) is not None:
friend_name = request.POST.get('post_note')
# save the object and indicate success
data['result'] = True
data['message'] = "Friend saved successfully"
...
if request.is_ajax():
return JsonResponse(data)
else:
return HttpResponseBadRequest()
When you are sending data via POST don't forget to pass along your CSRF token as in the example above. This assumes you have a form on the page you can get it from, otherwise you can use something like this to get it:
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = cookies[i].trim();
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');
If you don't want to deal with the CSRF token, you can mark the view with the #csrf_exempt decorator and remove the 'csrfmiddlewaretoken' data element from the Ajax call in the template, but it may not be ideal or the most secure. An example of that:
from django.views.decorators.csrf import csrf_exempt
from django.http import JsonResponse
#csrf_exempt()
def post_note_api(request):
...
If you post more details I can update my answer.

Related

Converting a JS Rest API Call into Python

I'm looking for assistance with translating a piece of sample code written in javascript into something that will work with Python. The sample code is for the 'POST Authenticate' Endpoint of CCH Axcess' Open Integration Kit, which sends a response containing a Security Token
URL: https://api.cchaxcess.com/api/AuthServiceHelp/v1.0/help/operations/Authenticate
Sample Code:
var _restIntegratorKey = "{User Integrator Key}"; // Please use this variable as global variable as all subsequent call required this integrator key to pass
var _restHostUrl = "{host url}"; // i.e. "{Protocol}://{host name}/api"
var request = $.ajax({
url: _restHostUrl + "/AuthService/v1.0/Authenticate",
contentType: "application/json; charset=utf-8",
type: "GET",
dataType: "json"
});
var request = {
UserName: "{username}", // Specify Username
UserSid: "anyone",
Password: "{password}", // Specify Password
Realm: "{accountnumber}" // Specify Account number
};
var request = $.ajax({
url: _restHostUrl + "/AuthService/v1.0/Authenticate",
data: JSON.stringify(request),
beforeSend: _setHttpHeader,
contentType: "application/json",
type: "POST",
dataType: "json"
});
request.done(function (data, textStatus, jqXHR) {
// This method block will be executed on succefull execution of api and will return security token.
// Below statement will store returned security token into browser cookie named: "CchNGAuthToken". you can use any other way to persist this token.
// This security token we required to pass in header for other rest api calls
document.cookie = "CchNGAuthToken=" + data.Token;
});
request.fail(function (jqXHR, textStatus, err) {
// This method block will be executed if API returns any error.
});
// Please keep these below two methods, As both will be used in subsequent call, to get SSOToken from Cookie
// set Security token and integratorkey into request header
function _setHttpHeader(xhr) {
var ssoToken = _getSessionCookie("CchNGAuthToken"); // Read security token from document cookie which we set during authentication rest api call
xhr.setRequestHeader("Security", ssoToken);
xhr.setRequestHeader("IntegratorKey", _restIntegratorKey);
};
// Get session cookie
function _getSessionCookie(name) {
var key = name + "=";
var cookie = "";
if (document.cookie.length > 0) {
var begin = document.cookie.indexOf(key)
if (begin != -1) {
begin += key.length
var end = document.cookie.indexOf(";", begin);
if (end == -1)
end = document.cookie.length;
cookie = unescape(document.cookie.substring(begin, end))
}
}
return cookie;
};
I have an LIC file with the IntegratorKey stored in XML format, like:
<?xml version="1.0"?>
<IntegratorInfo>
<IntegratorKey>XXXXX-XXX-XXX-XXXX</IntegratorKey>
</IntegratorInfo>
I think my primary issue is identifying the values of the 'ssoToken' and '_restIntegratorKey' variables once they're assigned inside the '_setHttpHeader' function.
My attempt:
def getcchauth():
import requests
integratorkey = getintkey()
cookie = getcookie()
authheaders = {
'Security': cookie,
'IntegratorKey': integratorkey,
'content-type': 'application/json; charset=utf-8'
}
cchlogin = {
'UserName':"user",
"UserSid": 'anyone',
'Password': 'password',
'Realm' : '123456',
}
authattempt = requests.post(resthosturl+endpoint, data = cchlogin,
headers=authheaders)
print(authattempt.headers)
def getcookie():
import requests
import json
cookieresponse = requests.get(resthosturl+apiservdir,
headers = headers)
cookieresponse = json.dumps(cookieresponse.headers.__dict__['_store'])
cookieresponse = json.loads(cookieresponse)
cookie = 'CchNGAuthToken=' + cookieresponse['set-cookie'][1].split(';')[0].strip() + ';'
print(cookie)
return cookie
Thanks!

Accessing Django View data fro JavaScript using Fetch Api

I'm trying to get data from Django view using fetch API but the fetch API isn't reaching the Django view.
function connect(username) {
alert('connect');
let promise = new Promise((resolve, reject) => {
// get a token from the back end
let data;
alert("before append")
// data.append('csrfmiddlewaretoken', $('#csrf-
helperinput[name="csrfmiddlewaretoken"]').attr('value'));
alert("vc")
fetch("/videocall/", {
method: 'POST',
// headers: {
// "X-CSRFToken": getCookie("csrftoken"),
// "Accept": "application/json",
// "Content-Type": "application/json"
// },
headers:{
'Accept': 'application/json',
'X-Requested-With': 'XMLHttpRequest', //Necessary to work with request.is_ajax()
'X-CSRFToken': csrftoken,
},
//credentials: "same-origin",
body: JSON.stringify({'username': username})
}).then(res => res.json()).then(_data => {
// join video call
alert("Joint")
data = _data;
return Twilio.Video.connect(data.token);
}).then(_room => {
alert("room")
room = _room;
room.participants.forEach(participantConnected);
room.on('participantConnected', participantConnected);
room.on('participantDisconnected', participantDisconnected);
connected = true;
updateParticipantCount();
connectChat(data.token, data.conversation_sid);
resolve();
}).catch(e => {
alert("catch")
console.log(e);
reject();
});
alert(promise)
});
return promise;
};
Here's my django view
def videocall(request):
print("Trying to login")
if request.method == "POST":
print("Trying to login")
It's not even printing trying to login which i printed in django view. I think there's some problem in URL in fetch.
I'm new to Django please help me in this regard
I had a similar issue but this code below is working fine both for get and post requests in Django 3.1.4 and Python 3.8.
//js
const AssignStaffForm = () => {
fetch('/app/get_users/', {
method: "GET",
credentials: "same-origin",
headers: {
Accept: "application/json",
"X-Requested-With": "XMLHttpRequest",
"X-CSRFToken": getCookie("csrftoken"),
},
})
.then((res) => res.json())
.then((data) => {
// then I use this data in an html form.
console.log(data)
})
.catch((err) => {
console.log("err in fetch", err);
});
};
#url dispatcher
path('get_users/', views.get_users, name='get_users'),
#view
import json
from django.http.response import HttpResponse
def get_users(request):
if request.method == 'GET':
users=[]
for user in User.objects.all():
users.append({'id':user.id, 'name': user.get_full_name()})
data = json.dumps({'users': users})
return HttpResponse(data, content_type='application/json')
Note:
I had earlier split my views and forgot to delete the original view functions from the main view file and this seemed to be the cause of the error in my case.

Django take value from url

I have problem with take value from url (?site=value). When I had function in views.py it was work, but now I moved this to another file. Can someone solve this problem?
functionAjax.py:
def htmlMain(request):
if request.is_ajax and request.method == "POST":
UrlCut = request.GET.get('site','Main')
Messages = NewsMessage.objects.all().order_by('-Data').values()
context = {
"Messags" : Messages
}
return render(request, 'ajax'+UrlCut+'.html', context)
AjaxFunction.js:
$.urlParam = function(name){
var results = new RegExp('[\?&]' + name + '=([^&#]*)').exec(window.location.href);
if (results==null){
return null;
}
else{
return results[1] || 0;
}
}
let tech = ""
if($.urlParam('site') != null)
{
tech = "?site=" + $.urlParam('site');
}
UrlSet = "/get/ajax/validate/MainSite"+tech;
$.ajax({
url: UrlSet,
data: $('#FormSite').serialize(),
type: "POST",
async:false,
success: function(response) {
$("#AjaxChange").replaceWith(response);
},
error: function(data)
{
alert('Bad connection');
console.log(data);
}
});
use 'Site' instead of 'site' to get Site=value
UrlCut = request.GET.get('Site', 'Main')

How is MultiValueDictKeyError and AttributeError related in Django here?

I have a function in Django that I am trying to solve from my previous question here. While trying out my own solutions, I have made significant updates but I encounter an error.
I'm trying this out right now:
def view_routes(request, query=None):
routes = None
if query is None:
routes = Route.objects.all()
else:
#View: Routes in Queried Boundary
if request.method == 'POST':
return HttpResponse("OK")
elif request.method == 'GET':
json_feature = json.loads(request.GET.get('geo_obj', False))
#json_feature = json.loads(request.GET['geo_obj'])
geom = make_geometry_from_feature(json_feature)
routes = Route.objects.filter(wkb_geometry__within=geom[0])
print("Total Routes Filtered: " + str(Route.objects.filter(wkb_geometry__within=geom[0]).count()))
#Render to Django View
routes_json = serialize('geojson', routes, fields=('route_type', 'route_long', 'route_id', 'wkb_geometry',))
routes_geojson = json.loads(routes_json)
routes_geojson.pop('crs', None)
routes_geojson = json.dumps(routes_geojson)
#return render(request, 'plexus/view_routes.html', {'routes':routes})
return redirect('routes_view', query)
I am having trouble switching/commenting out between these two lines:
json_feature = json.loads(request.GET.get('geo_obj', False))
json_feature = json.loads(request.GET['geo_obj'])
Both presents an error respectively:
TypeError: the JSON object must be str, not 'bool'
django.utils.datastructures.MultiValueDictKeyError: "'geo_obj'"
Edited function with AJAX inside:
function sendQueryData(url, query){
url =url.replace('query' , query);
if (query === ""){
alert("City Input Required");
}else{
if(geo_obj === null){
alert("Click Search Button...")
}else{
$.ajax({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
},
type: "GET",
url: url,
dataType: 'html',
data: {
'geo_obj' : JSON.stringify(geo_obj)
},
success: function(data){
alert(data);
window.location.href = url;
//var result = $('<div />').append(data).find('#list-group').html();
//$('#list-group').html(result);
},
error: function(xhr, textStatus, errorThrown) {
alert('Request Failed' + textStatus + ":" + errorThrown);
}
});
}
}
}
Try using json.loads(request.body) if you are passing raw JSON, request.GET['foo'] is for form-encoded data

POST request to view function

I want to send POST request to view function. Now I am getting 500 error. I could not figure out where is the problem. The view function is receiving POST request but not returning any data.
EDIT: Now problem with 500 error solved. But how should I return form for editing object?
Template:
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');
function editParticipant(event_id, row_id){
var postdata = {
'csrfmiddlewaretoken': csrftoken
}
$.post( "/edit-participant-" + event_id + "/", postdata, function( data ) {
console.log(data);
});
}
View:
def edit_participant(request, participant_id):
participant = Participant.objects.get(pk=participant_id)
form = RegisterToEvent(request.POST or None, instance = participant)
if form.is_valid():
form.save()
return HttpResponseRedirect('/event-%s' %2)
data = {'form': form}
return JsonResponse(data)
URL:
url(r'^edit-participant-(?P<participant_id>[0-9]+)/$', 'event.views.edit_participant', name='edit_participant'),
Your view doesn't return a response
def edit_participant(request, participant_id):
return JsonResponse({'data':"Test"})
You should also turn on debug in the settings by setting DEBUG to true, it will tell you exactly what the error is, just remember to turn this off before production. You can also implement error logging.
There isn't anything about this function that needs to use ajax requests. If you want to keep the same page if the form isn't valid, then just return the form errors and do something with them
data = { 'errors': form.errors }
But this doesn't make much sense to me when you can just load the page again with a form and let django do it for you with its form rendering.
return render(request, 'yourhtml.html', {form: form})

Categories