AJAX post-ing of python dictionary leads to JSONDecodeError - python

I am passing a python dictionary to a template then $.post-ing it to a view in django,
and when I try to json.loads it in my post view, I get JSONDecodeError.
Anyone know how I can fix this?
//1. vars to templates
#login_required
def bracket(request):
'''
:param request:
:return:
'''
...
context = {'arr':json.dumps(tournament_games_json_serializable), 'nested':nested_tournament_games['rounds']}#{'latest_question_list': latest_question_list}
return render(request, 'madness/bracket.html', context)
//2. AJAX post of template var
$.post('{% url "update_bracket" %}',
{ bracketData: "{{arr}}" },
function(data, status, xhr) {
console.log(JSON.stringify(data));
var nested = JSON.stringify(data);
}).done(function() { })
.fail(function(jqxhr, settings, ex) { alert('failed, ' + ex); });
//3. update_bracket
#csrf_exempt
def update_bracket(request):
bracketData = request.POST['bracketData']
print(json.loads(bracketData))
...
where tournament_games_json_serializable is
tournament_games_json_serializable
{'round_1_game_1': {'players': (2, 3), 'winner': None, 'loser': None, 'done': False}, 'round_2_game_1': {'players': (1, 'winner of Round 1 Game 1'), 'winner': None, 'loser': None, 'done': False}}
request.POST['bracketData']
'{"round_1_game_1": {"players": [2, 3]...
json.loads(bracketData)
json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2

Use html.unescape():
import json
import html
bracketData = '{"round_1_game_1": {"players": [2, 3]}}'
print(json.loads(html.unescape(bracketData)))
Output:
{'round_1_game_1': {'players': [2, 3]}}

Did you try to use safe filter?
{ bracketData: "{{arr|safe}}" },

Related

How to remove double quote from key value in dictionary

I have this payload:
"cardType": "CHOICE",
"step": 40,
"title": {"en-GB": "YOUR REPORT"},
"description": {"en-GB": ""},
"options": [
{"optionId": 0, "text": {"en-GB": "Ask me"}},
{"optionId": 1, "text": {"en-GB": "Phone a nurse"}},
{"optionId": 2, "text": {"en-GB": "Download full report"}},
],
"_links": {
"self": {
"method": "GET",
"href": "/assessments/898d915e-229f-48f2-9b98-cfd760ba8965",
},
"report": {
"method": "GET",
"href": "/reports/17340f51604cb35bd2c6b7b9b16f3aec",
},
},
}
I then url encode it like so and redirect to a report view:
url = reverse("my-reports")
reverse_url = encodeurl(data, url)
The urlencode output is returned as this:
"/api/v2/ada/reports?cardType=CHOICE&step=40&title="
"%7B%27en-GB%27%3A+%27YOUR+REPORT%27%7D&description="
"%7B%27en-GB%27%3A+%27%27%7D&options="
"%5B%7B%27optionId%27%3A+0%2C+%27text%27%3A+%7B%27en-GB"
"%27%3A+%27Ask+me%27%7D%7D%2C+%7B%27optionId%27%"
"3A+1%2C+%27text%27%3A+%7B%27en-GB%27%3A+%27Phone+a+nurse"
"%27%7D%7D%2C+%7B%27optionId%27%3A+2%2C+%27text%27%3A+%7B"
"%27en-GB%27%3A+%27Download+full+report%27%7D%7D%5D&_links="
"%7B%27self%27%3A+%7B%27method%27%3A+%27GET%27%2C+%27href%27%"
"3A+%27%2Fassessments%2F898d915e-229f-48f2-9b98-cfd760ba8965"
"%27%7D%2C+%27report%27%3A+%7B%27method%27%3A+%27GET%27%"
"2C+%27href%27%3A+%27%2Freports%2F"
"17340f51604cb35bd2c6b7b9b16f3aec%27%7D%7D"
In my report view I get the payload from the url query string:
class Reports(generics.GenericAPIView):
permission_classes = (permissions.AllowAny,)
def get(self, request, *args, **kwargs):
result = request.GET
data = result.dict()
print(data)
Now the problem is that the output of the transferred data which is printed above has quotes for nested keys.
{
'cardType': 'CHOICE',
'step': '40', 'title': "{'en-GB': 'YOUR REPORT'}",
'description': "{'en-GB': ''}",
'options': "[{'optionId': 0,
'text': {'en-GB': 'Ask me'}},
{'optionId': 1, 'text': {'en-GB': 'Phone a nurse'}}, {'optionId': 2, 'text': {'en-GB': 'Download full report'}}]",
'_links': "{'self': {'method': 'GET', 'href': '/assessments/898d915e-229f-48f2-9b98-cfd760ba8965'}, 'report': {'method': 'GET', 'href': '/reports/17340f51604cb35bd2c6b7b9b16f3aec'}}"
}
Notice the double quote in the "description", "options" keys etc.
Is there a way to remove this or pass this across to the view so that when I unwrap it I have the same data I started with.
Thanks
import urllib.parse
import json
# convert your dict to a string
json_string = json.dumps(your_payload)
# urlencode the json string
encoded = urllib.parse.quote(json_string.encode('utf-8'))
# build the url
url = reverse("my-reports")
reverse_url = f"{url}?payload={encoded}"
Then in your view:
class Reports(generics.GenericAPIView):
permission_classes = (permissions.AllowAny,)
def get(self, request, *args, **kwargs):
payload = request.GET.get('payload')
# do the encoding process in reverse
urldecoded = urllib.parse.unquote(payload)
data = json_loads(urldecoded)
print(data)

Replace ajax json for python json in Django

I'm trying change Ajax json url to python variable with a json in Django. As you can see the url in both cases are the same so I can't understand what is going on.
Thanks in advance.
What I'm looking for and does not work
<script>
$(document).ready(function() {
var table = $('#users').DataTable({
"ajax": "{{ es_docs }}",
my view:
#login_required(login_url="/login/")
def index(request):
context = {}
context['segment'] = 'index'
html_template = loader.get_template( 'index.html' )
resp = requests.get("https://gyrocode.github.io/files/jquery-datatables/arrays_id.json").json()
context['es_docs'] = resp
return HttpResponse(html_template.render(context, request))
Template.html:
<script>
$(document).ready(function() {
var table = $('#users').DataTable({
"ajax": "https://gyrocode.github.io/files/jquery-datatables/arrays_id.json",
'columnDefs': [
{
'targets': 0,
'checkboxes': {
'selectRow': true
}
}
],
'select': {
'style': 'multi'
},
'order': [[1, 'asc']]
});
This:
resp = requests.get(...)
Returns a response object. To get the json data do this:
response = requests.get(...)
if response.status_code != 200:
# handle errors:
else:
json_data = response.json()
context['es_docs'] = json_data

Stripe IntegrationError: stripe.redirectToCheckout: You must provide one of lineItems, items, or sessionId

I've got a Django website and I'm trying to integrate Stripe using Django the Stripe API on the backend and Vue.js on the frontend. However, when I try to run the checkout link that's supposed to redirect me to the payment processing page, I get the following error:
Error: IntegrationError: stripe.redirectToCheckout: You must provide one of lineItems, items, or sessionId.
at new r (https://js.stripe.com/v3/:1:6143)
at Js (https://js.stripe.com/v3/:1:165350)
at $s (https://js.stripe.com/v3/:1:165646)
at https://js.stripe.com/v3/:1:166758
at Qs (https://js.stripe.com/v3/:1:166769)
at nc (https://js.stripe.com/v3/:1:167275)
at Ec.redirectToCheckout (https://js.stripe.com/v3/:1:188030)
at http://localhost:8000/dashboard/myaccount/teams/plans/:342:39
Here's the Vue.js method responsible for this:
<script src="https://js.stripe.com/v3/"></script>
<script>
const PlansApp = {
data() {
return {
}
},
delimiters: ['[[', ']]'],
methods: {
subscribe(plan) {
console.log('Subscribe:', plan);
const stripe = Stripe('{{ stripe_pub_key }}');
fetch('/dashboard/myaccount/teams/api/create_checkout_session/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': '{{ csrf_token }}'
},
body: JSON.stringify({
'plan': plan
})
})
.then(function(response) {
return response.json()
})
.then(function(session) {
console.log(session)
return stripe.redirectToCheckout({ sessionId: session.sessionId })
})
.then(function(result) {
if (result.error) {
console.log('Error:', result.error.message)
}
})
.catch(function(error) {
console.log('Error:', error);
});
}
}
}
Vue.createApp(PlansApp).mount('#plans-app')
</script>
And here's the Django code that creates the session on the backend:
#login_required
def create_checkout_session(request):
stripe.api_key = settings.STRIPE_SECRET_KEY
data = json.loads(request.body)
plan = data['plan']
if plan == 'basic':
price_id = settings.STRIPE_BASIC_PRICE_ID
else:
price_id = settings.STRIPE_PRO_PRICE_ID
try:
checkout_session = stripe.checkout.Session.create(
client_reference_id = request.user.userprofile.active_team_id,
success_url = '%s%s?session_id={CHECKOUT_SESSION_ID}' % (settings.WEBSITE_URL, reverse('team:plans_thankyou')),
cancel_url = '%s%s' % (settings.WEBSITE_URL, reverse('team:plans')),
payment_method_types = ['card'],
mode = 'subscription',
line_items = [
{
'price': price_id,
'quantity': 1
}
]
)
return JsonResponse({'sessionId': checkout_session['id']})
except Exception as e:
return JsonResponse({'error': str(e)})
I'm struggling to find out why I'm getting the error that I'm getting and would be grateful for any help!
I guest the problem come from the 'success_url' and the 'cancel_url'.
Try to add http:// or https:// in your url
Cordially

How to make an appointment and save it to database Flask?

I am making a small app where the client can make an appointment in a calendar, but I don't know how to save the appointment inside the database then show it to them after by date.
Full Edit:
I've created the calendar with some junk appointments as you can see below:
I want to save the appointment inside the database, so when any client hits on any date after submitting it, an ajax request will be sent to my views where I can handle the request, here is the view.py:
#abonent_panel_route.route('/panel/make/appointment/')
#abonent_panel_route.route('/panel/make/appointment/', methods=['GET', 'POST'])
def get_appo():
# user = User.query.filter_by(id=current_user.id).first_or_404()
import json
getData = str(request.args.getlist('data'))
data = json.loads(getData)
if data :
print "\n\n\n\n" + str(data['title']) + "\n\n\n\n"
return jsonify({'success': data})
else:
print "\n\n\n\n" + str(len(data)) + "\n\n\n\n"
return jsonify({'error': 'No data!'})
And here is the javascript code:
$(document).ready(function() {
var initialLocaleCode = 'ru';
var d = new Date();
var strDate = d.getFullYear() + "/" + (d.getMonth()+1) + "/" + d.getDate();
$('#calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay,listMonth'
},
defaultDate: strDate,
height: 650,
locale: initialLocaleCode,
navLinks: true, // can click day/week names to navigate views
selectable: true,
selectHelper: true,
select: function(start, end) {
var title = prompt('Event Title:');
var eventData;
if (title) {
eventData = {
title: title,
start: start,
end: end
};
$('#calendar').fullCalendar('renderEvent', eventData, true); // stick? = true
$(this).css({'background-color':'red'});
$.ajax({
type: 'POST',
url: '{{url_for("panel_abonent.get_appo")}}',
data: [eventData]
})
.done(function(data){
if(data.error){
console.log(eventData);
}
else {
console.log(eventData);
}
});
}
$('#calendar').fullCalendar('unselect');
},
editable: true,
eventLimit: true,
events: [
{
title: 'All Day Event',
start: strDate
},
{
title: 'Long Event',
start: '2017-04-18',
end: '2017-04-20'
},
{
id: 999,
title: 'Repeating Event',
start: '2017-04-20'
},
{
id: 999,
title: 'Repeating Event',
start: '2017-04-29'
},
]
});
$.each($.fullCalendar.locales, function(localeCode) {
$('#locale-selector').append(
$('<option/>')
.attr('value', localeCode)
.prop('selected', localeCode == initialLocaleCode)
.text(localeCode)
);
});
$('#locale-selector').on('change', function() {
if (this.value) {
$('#calendar').fullCalendar('option', 'locale', this.value);
}
});
});
Inside the console , I can see a list of data of the picked date, like title, start and end time, here it is:
Object {title: "asfawg", start: r, end: r}
start : r{
"_ambigTime":true,
"_ambigZone":true,
"_d" : "Thu Apr 06 2017 06:00:00 GMT+0600 (+06)",
"_fullCalendar":true,
"_i":"2017/4/19",
"_isAMomentObject":true,
"_isUTC":true,
"_isValid":true,
"_locale":e,
"_offset":0,
"_pf":Object,
"__proto__":Object,
"title":"asfawg"
}
In view.py, I've converted the dictionary to a list to make it easy to fetch the data from the list, so you have a key and the value, as you've seen above where I print the title print "\n\n\n\n" + str(data['title']) + "\n\n\n\n" I should get the value of the title which is asfawg, but I got nothing and the request always return No data. and the length of the list returns 0.
Please , anybody tells me where is the mistake that I've made.
I solved the problem, the eventData itself was a dictionary not a list.
So if i want to fetch the start date for example inside ajax request then to send it to my view.py, i would do something like:
data: {
'data': title,
'start': eventData['start']['_d'],
'end': eventData['end']['_d']
}
And I've changed a little bit my views, i added a function that took any json argument and return it as a json dictionary, i used flask_restful to do the job, here is the function:
def parse_arg_from_requests(arg, **kwargs):
from flask_restful import reqparse
parse = reqparse.RequestParser()
parse.add_argument(arg, **kwargs)
args = parse.parse_args()
return args[arg]
Next is very simple, just get the arguments one by one like the following order:
data = parse_arg_from_requests('data')
start = parse_arg_from_requests('start')
end = parse_arg_from_requests('end')
return render_template('panel/panel.html')

Parsing JSON-file with Python in Django

I have query where I fetch JSON-file and want to show the data in table in HTML. I get now error: TypeError: string indices must be integers in line: 'status': item['status'],. Is the problem with outer brackets, because they are missing in json or what?
views.py code
json_obj = urllib2.urlopen(url)
data = json.load(json_obj)
results = []
for item in data:
results.append({
'status': item['status'],
'device': item['device'],
})
return render(request, 'index/index.html', {'objects_list': results})
JSON-file:
{
“version": “3.62”,
"treesize": 2,
"": [
{
“status”: “up”,
"device": “someDeviceName1”,
}
{
“status”: “up”,
"device": “someDeviceName2”,
}]
}
I don't know whether you accidentally copied the JSON content wrong or not but what you should do is:
>>> for item in data[""]:
... results.append({ ...

Categories

Resources