making json array in django - python

# 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

AttributeError: Could not locate column in row for column 'to_dict'

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.

500 (Internal Server Error) and Unexpected token < in JSON at position 0

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)

Mongodb, create update in python

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)

Convert recursive POST data to JSON object

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
}
});

Django View function. Can't get a value from Dictionary, only full dictionary

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]

Categories