Pass array of objects from JS to rails controller for creation - javascript

I am trying to pass an array of objects from my JS to my Rails controller so that I can loop through the array and check to see if each object exists, and if not, create it. I'm having a difficult time getting my strong params setup properly. Seems like no matter what I do, I'm getting some kind of an error about unpermitted params.
My JS that is creating and sending the data:
function addGame(gameData) {
var parser = new DOMParser();
var xmlDoc = parser.parseFromString(gameData,"text/xml");
// Check categories and create any new categories that need created
var gameCategories = [];
// for each category in the JSON push into gameCategories
var x = xmlDoc.getElementsByTagName("link").length;
var i = 0
for (i = 0; i < x ; i++) {
var type = xmlDoc.getElementsByTagName("link")[i].getAttribute("type");
if (type == "boardgamecategory") {
var categoryData = {
name: xmlDoc.getElementsByTagName("link")[i].getAttribute("value"),
bgg_id: xmlDoc.getElementsByTagName("link")[i].getAttribute("id")
};
gameCategories.push(categoryData);
}
}
console.log(gameCategories);
// Try sending all of the categories at once
$.ajaxSetup({
headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') }
});
$.ajax({
url: '/categories',
type: 'POST',
dataType: 'json',
data: { categories: JSON.stringify(gameCategories)},
success: function (response) {
console.log(response);
}
});
My rails controller
class CategoriesController < ApplicationController
def create
logger.debug category_params
# #category = Category.find_or_initialize_by(category_params)
# if #category.save
# logger.debug "Category Saved"
# else
# flash[:danger] = "There was a problem creating one of the game categories ¯\_(ツ)_/¯"
# redirect_to root_url
# end
end
private
def category_params
params.permit(categories: [])
end
end
Right now if I run this the server log shows
Started POST "/categories" for ::1 at 2019-09-19 21:45:33 -0400
Processing by CategoriesController#create as JSON
Parameters: {"categories"=>"[{\"name\":\"Adventure\",\"bgg_id\":\"1022\"},{\"name\":\"Exploration\",\"bgg_id\":\"1020\"},{\"name\":\"Fantasy\",\"bgg_id\":\"1010\"},{\"name\":\"Fighting\",\"bgg_id\":\"1046\"},{\"name\":\"Miniatures\",\"bgg_id\":\"1047\"}]"}
User Load (0.5ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
↳ app/helpers/sessions_helper.rb:18
Unpermitted parameter: :categories
{}
No template found for CategoriesController#create, rendering head :no_content
Completed 204 No Content in 95ms (ActiveRecord: 22.8ms)
Thanks in advance for any advice!

Try this
$.ajax({
url: '/categories',
type: 'POST',
dataType: 'json',
data: { categories: gameCategories},
success: function (response) {
console.log(response);
}
});
def category_params
params.permit(categories: [:name, :bgg_id])
end

Related

How to Parse LocalStorage JSON object in Django View from Ajax?

I am trying to submit localstorage data via a POST request using the below jquery ajax method. How should I write my view so I can Parse my JSON object and get a hold of "product_id" to execute the below command in my Django view. Please see a copy of my view below.
Trying since one week, but I failed to fix the issue
Is there any better way of achieving this ?
My Ajax:
$(document).ready(function() {
var compare = localStorage.getItem("comparisionItems");
var compareObj = JSON.parse(compare);
var data_url = window.location.href;
console.log(compare)
console.log(compareObj)
$.ajax({
url: data_url,
type: "POST",
data: {'compare_id': compareObj },
headers: { "X-CSRFToken": $.cookie("csrftoken") },
success: function (result) {
console.log("Success")
},
});
});
and My Views:
def compare(request):
is_ajax = request.headers.get('X-Requested-With') == 'XMLHttpRequest'
if is_ajax and request.method == "POST":
compare_id= request.POST.getlist('compare_id[itemIds]')
product = get_object_or_404(Products, id=compare_id)
context={ 'product':product}
return render (request, './compare.html', context)
Actually my localStorage is on following format:
("comparisionItems"({ images: products, itemIds: itemIds }));
Can you please help me how can I pass itemIds to views and return item from views for the itemsIds?
Console log for console.log(compareObj)
https://imgur.com/MxdZrgy
since .is_ajax() is deprecated you cant use that, but you can check if the request is an XMLHttpRequest like below.
from django.shortcuts import get_object_or_404
def compare(request):
is_ajax = request.headers.get('X-Requested-With') == 'XMLHttpRequest'
if is_ajax and request.method == "POST":
compare_id = request.POST.get('compare_id')
product = get_object_or_404(Products, product_id=id)
context={ 'product':product,}
return render (request, './ecommerce/compare.html', context)
note; the get_object_or_404 is just a shortcut for:
try:
product = Products.objects.get(product_id=id)
except:
raise Http404

Using Ajax to passing multiple value and fetching data in view to export it in excel in Django

View.py
def export(request):
if request.is_ajax():
ourid = request.GET.getlist("terid")
Case_Detail = Case_Info_Resource()
for i in ourid:
print(i)
queryset = Case_Info.objects.filter(id=i)
dataset = Case_Detail.export(queryset)
response = HttpResponse(
dataset.xls, content_type='application/vnd.ms-excel')
response['Content-Disposition'] = 'attachment; filename="persons.xls"'
print("breakpoint")
return response
Ajax Script
<script>
$(document).ready(function () {
$('#Download').click(function () {
var list = [];
$("input:checkbox[name='checkbox']:checked").each(function () {
list.push($(this).val());
});
$.ajax({
url: '/Account_Manager/Download/',
type: 'GET',
data: { 'terid': list },
traditional: true,
dataType: 'html',
success: function () {
alert("The best cricketers are: " + list.join(", "));
}
});
});
});
</script>
Error:
The view Apps.views.export didn't return an HttpResponse object. It returned None instead.
So, Ajax wants us to return the value in HttpResponse but I need to pass the response normally in order to download the excel which I am creating. I think I checked all the possible answers and struggling with it from the last 3 days. Thank you in advance for any help, suggestions, or edit.

django run custom views class method with one url

I'm new to django. I want to manage my database with custom methods inside the views file. for example, I have this code I would like to run with javascript - I wrote this code:
Js:
$.ajax({
type: 'POST',
url: '/ClassManager/',
data: {
data: data,
csrfmiddlewaretoken: csrftoken,
},
success: function() {
alert("IT WORKED")
},
error: function() {
alert('error');
}
})
views.py
def expfunc():
if request.method == 'POST':
user = User.objects.get(pk=1)
addlst = List(content = "list content", creator = user)
addlst.save()
urls.py
urlpatterns = [
path('ClassManager/', views.expfunc),
]
now, the problem is, that for every new function that I want to create in the views.py, I need to add another line in the urls.py.
my question is - if there a way to create a class with all of the custom methods, and access them with one url and different data?
for example:
Js:
$.ajax({
type: 'POST',
url: '/ClassManager/functionone()',
data: {
data: data
csrfmiddlewaretoken: csrftoken,
},
success: function() {
alert("IT WORKED")
},
error: function() {
alert('error');
}
})
views.py
class DatabaseManager():
def functionone(): # add new list
if request.method == 'POST':
user = User.objects.get(pk=1)
addlst = List(content = "list content", creator = user)
addlst.save()
def functwo(): # update username
if request.method == 'POST':
user = User.objects.get(pk=1)
user.id = 9
user.save()
def functhree(): # update list content
if request.method == 'POST':
user = User.objects.get(pk=1)
mylist = List.objects.get(pk=1)
mylist.content = "updated list content"
mylist.save()
urls.py
urlpatterns = [
path('ClassManager/functionone()', views.DatabaseManager.functionone),
]
I came from asp.net background where I wrote classes with functions that ran queries and that it how I managed my database, so can I do the same here?
Thanks In Advance!
You can use Class Based View to implement your views as Python objects instead of functions, but you can't call a class function with Ajax.

Send an array with ajax to my python function in django

I'm trying to send an array to my python function inside views.py but I can't. It always crash with a keyError because is not recognising the data from js.
Code:
Python function in views.py:
def cargar_datos_csv(request):
if request.method == 'POST':
filtros = request.POST['node']
print(filtros)
ctx = {'A':filtros}
return JsonResponse(ctx)
JS
var csrftoken = $("[name=csrfmiddlewaretoken]").val();
var frutas = ['Manzana', 'Banana'];
$.ajax({
url: '/../../data_bbdd/',
type: 'POST',
headers:{"X-CSRFToken": csrftoken},
data: {
'node': frutas,
},
dataType: "json",
cache: true,
success: function(response) {
coords = JSON.stringify(response.A);
alert(coords);
}
});
How can I send an array to my python function?
Thank you very much.
Because node is a list it will be posted as node[] by JQuery so you can get it using request.POST['node[]'] or request.POST.getlist('node[]')
More informations on why this is the behavior of JQuery on this stackoverflow's answer :django - getlist()

django ajax call return 403 bad request

I'm trying to compile project https://github.com/kannan4k/django-carpool
please refer this project repo for this issue.
and end up with following error during ajax call.
Failed to load resource: the server responded with a status of 400 (BAD REQUEST).
I know this is because of ajax post request & CSRF tokens.
following is my setting.
1. disable "django.middleware.csrf.CsrfViewMiddleware"
2. in new_trip page I have a button (Postdata)so this button sends an ajax request.
My View:-
#login_required
def save_journey(request):
if request.is_ajax() and request.method == "POST":
try:
res = json.loads(request.body)
cords = res['cords']
cords = [[x['d'], x['e']] for x in cords]
distance = res['distance']
start_place = res['start']
end_place = res['end']
clusters = clusterize_latlngs(cords, distance)
time = datetime.datetime.strptime(res['time'], "%m/%d/%Y %H:%M")
Trip.objects.create(user=request.user, time=time, cluster=json.dumps(clusters), travel_distance=distance,
start_place=start_place, end_place=end_place)
return HttpResponse()
except:
return HttpResponseBadRequest()
else:
return HttpResponseNotAllowed(['POST'])
Ajax call (home.js)
function postData() {
radius = 0;
var url = "/save_journey/";
var dataType = 'json';
if (type == 'r') {
radius = $('#radius').val();
url = "/get_results/";
dataType = 'html';
}
var data = JSON.stringify({
cords: myroute,
time: document.getElementById('dateStart').value,
start: document.getElementById('startPlace').innerHTML,
end: document.getElementById('endPlace').innerHTML,
radius: radius,
distance: distance
});
$.ajax({
type: "POST",
url: url,
dataType: dataType,
data: data,
success: function (data) {
if (type == 'r') {
window.location.href = "/search_results/";
}
else {
window.location.href = '/trip_success/';
}
},
error: function () {
console.log('Error getting options list...')
}
});
console.log(data);
}
this code is not able to call /save_journey/ URL.
I tried many answers from stack overflow & didn't figure out what is the problem .
You should never disable csrftoken unless you're absolutely sure about what you're doing. It's an important part of the security features implemented in Django.
Here is an example of how you can use Ajax with Django with csrftoken:
You can use Ajax Post to send JSON to Django and then handle the arguments as a dict(). Here is an example:
In browser (JQuery/JavaScript):
function newModule() {
var my_data = $("#my_element").val(); // Whatever value you want to be sent.
$.ajax({
url: "{% url 'modules' %}", // Handler as defined in Django URLs.
type: "POST", // Method.
dataType: "json", // Format as JSON (Default).
data: {
path: my_data, // Dictionary key (JSON).
csrfmiddlewaretoken:
'{{ csrf_token }}' // Unique key.
},
success: function (json) {
// On success do this.
},
error: function (xhr, errmsg, err) {
// On failure do this.
}
});
In server engine (Python):
def handle(request):
# Post request containing the key.
if request.method == 'POST' and 'my_data' in request.POST.keys():
# Retrieving the value.
my_data = request.POST['my_data']
# ...
Hope this helps.

Categories