# view code:
response_data = []
for p in product:
response_record = {}
response_record['pname'] = p.name
response_data.append(response_record) ...
# make json type array end
return HttpResponse(json.dumps(response_data, default=date_handler,
sort_keys=True), "application/json")
For example, i want to get values like response.product.pname in ajax response:
# expected json output:
{
["product": {"pname": 'a', "pid": '2'}]
}
I finaly found choice
view:
def search(request):
if request.method == 'POST' and request.is_ajax():
value = request.POST.get('value')
products = product.objects.filter(p_name__icontains=u'%s' % value)#Convert to unicode
#make json type array begin
response_data = []
final_response = {}
for p in product:
response_record = {}
response_record['pname'] = p.name
response_record['pid'] = p.id
response_data.append(response_record)
final_response["product"] = response_data
#make json type array end
return HttpResponse(json.dumps(final_response, default=date_handler, sort_keys=True), "application/json")
else:
return HttpResponse("Bad Request Detected!! :(")
JS:
$.ajax({
type: 'POST',
url: '/Search/',
data:{value:val},
dataType: "json",
success:function(response)
{
$.each(response.product, function (i, val)
{
alert(val.pname+" "+val.pid);
}
);
}
Related
I use flask with datatable.js plugin with ajax. I am getting following error. Looks like this error is thrown at the end of my view (see code at the bottom). I am not able to locate the cause of issue, any thoughts?
Error: (thrown from view shown below in code)
'data': [it.to_dict() for it in query],
AttributeError: Could not locate column in row for column 'to_dict'
This is my model:
class DiskSpaceView(Database.db.Model, UserMixin):
__tablename__ = 'view_space'
__table_args__ = {"schema":"config"}
column_not_exist_in_db = Database.db.Column(Database.db.Integer, primary_key=True) # just add for sake of this error, dont add in db
object_type = Database.db.Column(Database.db.String)
schemaname = Database.db.Column(Database.db.String)
tablename = Database.db.Column(Database.db.String)
indexname = Database.db.Column(Database.db.String)
object_size_bytes = Database.db.Column(Database.db.String)
object_size = Database.db.Column(Database.db.String)
def to_dict(self):
return {
'column_not_exist_in_db': random.getrandbits(64),
'object_type': self.object_type,
'schemaname': self.schemaname,
'tablename': self.tablename,
'indexname': self.indexname,
'object_size_bytes': self.object_size_bytes,
'object_size': self.object_size
}
This is my Ajax call:
$(document).ready(function () {
var table = $("#dataTbDiskSpace").DataTable({
scrollY: "600px",
scrollCollapse: true,
paging: true,
ajax: "/api/datadiskspace",
serverSide: true,
pageLength : 200,
success: function (ajax) {
console.log("test.js >> DataTable ajax >>>" + JSON.stringify(ajax));
},
columns: [
{ data: "object_type" },
{ data: "schemaname"},
{ data: "tablename"},
{ data: "indexname"},
{ data: "object_size_bytes"},
{ data: "object_size"}
],
columnDefs: [
{
defaultContent: "-",
targets: "_all",
},
],
});
});
This is my view:
#userviews.route('/api/datadiskspace')
def datadiskspace():
query = DiskSpaceView.query.with_entities(DiskSpaceView.object_type, DiskSpaceView.schemaname, DiskSpaceView.tablename,DiskSpaceView.indexname,DiskSpaceView.object_size_bytes, DiskSpaceView.object_size)
print(query)
# search filter
search = request.args.get('search[value]')
if search:
query = query.filter(DatabasePostgres.db.or_(
DiskSpaceView.tablename.like(f'%{search}%'),
DiskSpaceView.indexname.like(f'%{search}%')
))
total_filtered = query.count()
# sorting
order = []
i = 0
while True:
col_index = request.args.get(f'order[{i}][column]')
if col_index is None:
break
col_name = request.args.get(f'columns[{col_index}][data]')
if col_name not in ['object_type', 'schemaname', 'tablename', 'indexname','object_size_bytes','object_size']:
col_name = 'schemaname'
descending = request.args.get(f'order[{i}][dir]') == 'desc'
col = getattr(DiskSpaceView, col_name)
if descending:
col = col.desc()
order.append(col)
i += 1
if order:
query = query.order_by(*order)
# pagination
start = request.args.get('start', type=int)
length = request.args.get('length', type=int)
query = query.offset(start).limit(length)
#debug
counter = 1
for i in query:
print(i)
print(counter)
counter += 1
# response
return {
'data': [it.to_dict() for it in query],
'recordsFiltered': total_filtered,
'recordsTotal': DiskSpaceView.query.count(),
'draw': request.args.get('draw', type=int)
}
EDIT:
I think it may something to do with pagination - if i set for example 200 in my ajax call like: pageLength : 200 then in my view when i print (see #debug) it prints me 200 rows. When I for instance change to pageLength : 50. My print loop prints me 50 rows... I don't understand what's the case but this seems to be pretty intresting.
I'm trying to create a website based on guides. When it came to updating the basket through the buttons (decrease and increase), then trying to click on them, errors are issued: Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0, which refers to
.then((data) => {
location.reload()
});
cart.js:24 POST http://127.0.0.1:8000/update_item/ 500 (Internal Server Error)
which refers to
fetch(url, {
method:'POST',
headers:{
'Content-Type':'application/json',
'X-CSRFToken': csrftoken,
},
and i have error in console pycharm line 104, in updateItem
productId = data['productId']
KeyError: 'productId'
code cart.js:
var updateBtns = document.getElementsByClassName('update-cart')
for (i = 0; i < updateBtns.length; i++) {
updateBtns[i].addEventListener('click', function () {
var productId = this.dataset.stuff
var action = this.dataset.action
console.log('productId:', productId, 'Action:', action)
console.log('USER:', user)
if (user == 'AnonymousUser') {
console.log('User is not authenticated')
} else {
updateUserOrder(productId, action)
}
})
}
function updateUserOrder(productId, action){
console.log('User is authenticated, sending data...')
var url = '/update_item/'
fetch(url, {
method:'POST',
headers:{
'Content-Type':'application/json',
'X-CSRFToken': csrftoken,
},
body:JSON.stringify({'productId':productId, 'action':action})
})
.then((response) => {
return response.json();
})
.then((data) => {
location.reload()
});
}
views.py
def updateItem(request):
data = json.loads(request.body)
productId = data['productId']
action = data['action']
print('Action:', action)
print('Product:', productId)
customer = request.user.customer
product = Stuff.objects.get(id=productId)
order, created = Order.objects.get_or_create(customer=customer, complete=False)
orderItem, created = OrderItem.objects.get_or_create(order=order, product=product)
if action == 'add':
orderItem.quantity = (orderItem.quantity + 1)
elif action == 'remove':
orderItem.quantity = (orderItem.quantity - 1)
orderItem.save()
if orderItem.quantity <= 0:
orderItem.delete()
return JsonResponse('Item was added', safe=False)
Thank you in advance
What is your Python version?
From Python v3.0, json.loads() will only accept unicode string.
Maybe the problem is that you have to decode request.body first :
data = json.loads(request.body.decode('utf-8'))
If this is not the problem try to check what you are receiving. Because the "<" character looks like html or xml. For example, change your function to:
def updateItem(request):
data = json.loads(request.body)
return HttpResponse(data)
Here is my mongodb object. I need to write update function for "graded" field. Sometimes i need to create this field, sometimes update.
#api_view(['POST'])
def updateGrade(request):
db = connect_to_db()
data = json.loads(request.body)
db.update({ '_id': ObjectId(data["id"])},
{ "$set" : {
"worksheetSolutions.$[idx]": {"graded": data["status"]}
} },
{"arrayFilters":[{"idx":data["answerId"]}]}
)
q = db.find_one({'_id': ObjectId(data["id"])})
q['_id'] = str(q['_id'])
return JsonResponse(q, safe=False)
Here is my python code. (not correct at all as I see now)
data.id => _id
data.answerId => id of answer
data.status => true/false var
Ok, with some time i got it
def updateGrade(request):
db = connect_to_db()
data = json.loads(request.body)
db.update({ '_id': ObjectId(data["id"]), "worksheetSolutions.id": data["answerId"]},
{ "$set" : {
"worksheetSolutions.$.graded": data["status"]
} }
)
q = db.find_one({'_id': ObjectId(data["id"])})
q['_id'] = str(q['_id'])
return JsonResponse(q, safe=False)
I'm POSTing JSON via javascript to an endpoint as form data, not in the body. I'm doing this to avoid an extra CORS OPTIONS lookup. The JSON is formatted as:
$.ajax({
url: 'somewhere',
type: 'POST',
data: {
"foo": [
"a",
"b"
],
"bar": [
{
"biz": [
"c",
"d"
]
}
]
},
success: function(response) {
// something
}
});
When the query string comes through, it looks like foo%5B%5D=a&foo%5B%5D=b&bar%5B0%5D%5Bbiz%5D%5B%5D=c&bar%5B0%5D%5Bbiz%5D%5B%5D=d
I parse the query string with:
data = parse.unquote(data)
data = parse.parse_qs(data)
print(json.dumps(data))
But the resulting dict/json is
{
"foo[]": [
"a",
"b"
],
"bar[0][biz][]": [
"c",
"d"
]
}
This is problematic since I can't traverse the original keys. How can I convert the received value back into it's original JSON form?
This is what I have so far
def findValue(value):
if isinstance(value, dict):
value = findValue(list(value.keys())[0])
elif isinstance(value, list):
value = findValue(value[0])
return prepareValue(value)
def prepareKey(data, value=None):
print(data)
if isinstance(data, str):
match = re.findall('([a-zA-Z0-9_-]+)\[([a-zA-Z0-9_-]+)\](.*)', data)
return match[0]
if data[2] != '':
additional = prepareKey(data[2], value)
else:
additional = value
return {data[0]: {data[1]: additional}}
def prepareValue(value):
if len(value) == 1:
value = value[0]
return value
def preparePost(data, newData=False):
if isinstance(data, dict):
if not newData:
newData = {}
for key, value in data.items():
match = re.findall('([a-zA-Z0-9_-]+)\[([a-zA-Z0-9_-]+)\](.*)', key)
if len(match):
assignment = findValue(value)
thisData = prepareKey(match[0], assignment)
newData.update(thisData)
else:
newData[key] = prepareValue(value)
return newData
data = parse.unquote(data)
data = parse.parse_qs(data)
data = preparePost(data)
print(data)
It works moderately well but fails on the deeply nested values.
This is the real query I'm working with: foo=bar&cart%5Bcurrency%5D=USD&cart%5Banalytics%5D%5Blib%5D%5Bintegrations%5D%5B0%5D%5Boptions%5D%5BdefaultAttributes%5D%5BthemeId%5D=38654869555&cart%5Banalytics%5D%5Blib%5D%5Bintegrations%5D%5B0%5D%5Boptions%5D%5BdefaultAttributes%5D%5BcontentLanguage%5D=en
I can get as far as {'foo': 'bar', 'cart': {'currency': 'USD'}} but it fails on cart%5Banalytics%5D%5Blib%5D%5Bintegrations%5D%5B0%5D%5Boptions%5D%5BdefaultAttributes%5D%5BthemeId%5D=38654869555
Solution
Stringify the JSON and send the correct headers:
$.ajax({
url: 'somewhere',
type: 'POST',
contentType: 'application/x-www-form-urlencoded',
data: JSON.stringify({
"foo": [
"a",
"b"
],
"bar": [
{
"biz": [
"c",
"d"
]
}
]
}),
success: function(response) {
// something
}
});
I want to get a value from a dictionary which I get from request session
words = request.session['words']
In the Python console I get my expected result:
>>> words
{0: "value_0", 1: "value_1", 2: "value_2", 3: "value_3", 4: "value_4"}
>>> words[0]
'value_0'
I have a variable called wordcount = 0 and get the result exactly as expected, whatever else.
>>> words[wordcount]
'value_0'
But, If I try to get a value in my Django view function, it doesn't work
Here are my two view functions:
def first_view(request):
words = {}
wordcount = 0
request.session['wordcount'] = wordcount
for i in range(5):
words[i] = "value_" + str(i)
request.session['words'] = words
def second_view(request):
if request.method == "POST":
message = "checkpoint_1"
words = request.session['words']
wordcount = request.session['wordcount']
if request.POST.get("input"):
input = request.POST.get("input").upper()
message = words[wordcount]
data = {'message': message}
return JsonResponse(data)
The second view is called by an Ajax-Request
$(button).on('click', function(event) {
event.preventDefault();
var input = $('#input').val();
$.ajax({
method: "POST",
url: "/second_view/",
data: { "input": input },
dataType: "json",
context: this,
success: function (data) {
output.innerHTML = data.message;
}
});
});
My expectation is, that the Response data.message is 'value_1', but I get the 'checkpoint_1' message. If I replace the following part:
if request.POST.get("input"):
input = request.POST.get("input").upper()
message = words
data = {'message': message}
return JsonResponse(data)
I get the response message: {0: "value_0", 1: "value_1", 2: "value_2", 3: "value_3", 4: "value_4"}
why the hell I'm not getting what I expect: words[wordcount] -> 'value_0' equal result to words[0]