I keep getting the below error when I complete payment via Paypal in development:
JSONDecodeError at /checkout/thankyou
Expecting value: line 1 column 1 (char 0)
I have looked around and I can see that there is some issue with the format of the JSON, and my view can't process it. I can't figure out what the issue with my data is exactly, however. I want to use my Json data to create an order on my Django model once it has pulled through, however I can't get to that stage yet.
checkout.html script:
let bagContents = '{{ bag_products|safe }}';
const csrftoken = getCookie('csrftoken');
const paymentAmount = '{{ total | safe }}';
// Parse bagContents, then for each create a variable for name, id and quantity
let bag = JSON.parse(bagContents);
for (let i = 0; i < bag.length; i++) {
let itemName = bag[i].name;
let itemId = bag[i].id;
let itemQuantity = bag[i].quantity;
console.log(itemName);
console.log(itemId);
console.log(itemQuantity);
}
function completeOrder(){
let url = '{{ success_url }}'
fetch(url, {
method: 'POST',
headers:{
'Content-type':'application/json',
'X-CSRFToken': csrftoken,
},
body:JSON.stringify({'bagContents': 'bagContents'})
})
}
paypal.Buttons({
// Sets up the transaction when a payment button is clicked
createOrder: (data, actions) => {
return actions.order.create({
purchase_units: [{
amount: {
value: paymentAmount
}
}]
});
},
// Finalize the transaction after payer approval
onApprove: (data, actions) => {
return actions.order.capture().then(function (orderData) {
// Successful capture! For dev/demo purposes:
console.log('Capture result', orderData, JSON.stringify(orderData, null, 2));
const transaction = orderData.purchase_units[0].payments.captures[0];
completeOrder()
actions.redirect("{{ success_url }}");
// When ready to go live, remove the alert and show a success message within this page. For example:
// const element = document.getElementById('paypal-button-container');
// element.innerHTML = '<h3>Thank you for your payment!</h3>';
// Or go to another URL: actions.redirect('thank_you.html');
});
}
}).render('#paypal-button-container');
</script>
{% endblock %}
Views.py:
def order_success(request):
"""
View that displays the successful order page after an order has been
processed.
"""
print(request.body)
body = json.loads(request.body)
print('BODY:', body)
return JsonResponse('Success!', safe=False)
Print Statements:
b'{"bagContents":"[{\\"name\\": \\"Teddy Bear\\", \\"id\\": 2, \\"quantity\\": 3}, {\\"name\\": \\"Bath Toys\\", \\"id\\": 1, \\"quantity\\": 1}, {\\"name\\": \\"Chew Toy\\", \\"id\\": 4, \\"quantity\\": 2}]"}'
b''
BODY: {'bagContents': '[{"name": "Teddy Bear", "id": 2, "quantity": 3}, {"name": "Bath Toys", "id": 1, "quantity": 1}, {"name": "Chew Toy", "id": 4, "quantity": 2}]'}
Any help would be greatly appreciated!
Related
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.
I'm learning to work with JSON and so I'm running a simple example to create a list item in my template for each object in my django model. My output looks like this:
So I wanted each <li> to show just the actual value in Name. How can I amend my code to achieve that?
views.py
def Ajax(request):
if request.is_ajax():
exporter = serializers.serialize("json", Proforma.objects.all())
print(exporter)
data = json.dumps(exporter)
return HttpResponse(data, content_type='application/json')
$("#populate").click(function() {
$.ajax({
url: "/ajax/more",
success: function(data) {
for(i = 0; i < data.length; i++){
$('ul').append('<li>'+data[i]+'</li>');
}
}
});
});
EDIT:
Here is the output from the console:
(index):739 [{"model": "Poseidon.proforma", "pk": 24, "fields": {"Name": "greg", "Shipment": 4, "Exporter": "greg", "QuoteNo": "jiojo", "Date": "ijoi", "Consignee": 10, "MethodOfDispatch": "ujhiuh", "TypeOfShipment": "iuhiu", "PortOfLoading": "huyg", "PortOfDischarge": "uioj", "Terms": "iugh", "ProductCode": "utyg", "DescriptionOfGoods": "iuhi", "UnitQty": "ug", "UnitType": "t", "Price": "iuh", "Amount": "iy", "BankDetails": "guyt", "AdditionalInfo": "gy", "InvoiceTotal": "tf", "Place": "uyg", "SignatoryCompanyBuyer": "uyf", "SignatoryCompany": "utfy", "NameSignerBuyer": "guyg", "NameSigner": "uy", "SignatureBuyer": "fy", "Signature": "trf", "CreatedBy": "uyg"}}]
the problem is the ajax because you cant print a whole object in the li tag:
try this(would print "Poseidon.proforma" on the li tag):
$("#populate").click(function() {
$.ajax({
url: "/ajax/more",
success: function(data) {
var data = JSON.parse(data); // parse the string response to JSON
for(i = 0; i < data.length; i++){
$('ul').append('<li>'+data[i]["model"]+'</li>');
}
}
});
});
if you want a to understand the problem i think w3schools may help
I'm having trouble getting data from the backend (Python API) to show in react-table manually. I've read the documentation and I'm trying to use the example here: https://react-table.js.org/#/story/server-side-data
I'm only seeing data in one column and only for 6 records which is really weird. It's probably the way I'm mixing in async/await syntax with the example code which uses a promise. I was able to create a simple react-table fetching data with the same async/await syntax, but when I added the server-side data code from the example (the requestData function) it wouldn't work.
I've spent days on this and looking all over Stackoverflow and the internet. I'm a newbie so please go easy on me. Here's what I have:
import React from 'react'
import { render } from 'react-dom'
import ReactTable from 'react-table'
import api from 'src/api'
import { orderBy } from 'lodash'
// importing react-table css would not work so I added it using cdn link
const requestData = async (pageSize, page, sorted, filtered) => {
// api is a wrapper for axios.create()
const rawData = await api.admin.exercise.feed()
return new Promise((resolve, reject) => {
let filteredData = rawData;
if (filtered.length) {
filteredData = filtered.reduce((filteredSoFar, nextFilter) => {
return filteredSoFar.filter(row => {
return (row[nextFilter.id] + "").includes(nextFilter.value);
});
}, filteredData);
}
const sortedData = orderBy(
filteredData,
sorted.map(sort => {
return row => {
if (row[sort.id] === null || row[sort.id] === undefined) {
return -Infinity;
}
return typeof row[sort.id] === "string"
? row[sort.id].toLowerCase()
: row[sort.id];
};
}),
sorted.map(d => (d.desc ? "desc" : "asc"))
);
const res = {
rows: sortedData.slice(pageSize * page, pageSize * page + pageSize),
pages: Math.ceil(filteredData.length / pageSize)
};
resolve(res);
});
};
export class ExerciseList extends React.Component {
constructor() {
super();
this.state = {
data: [],
pages: null,
loading: true
};
this.fetchData = this.fetchData.bind(this);
}
setLoading(loading) {
this.setState({ loading })
}
fetchData(state, instance) {
this.setLoading(true);
requestData(
state.pageSize,
state.page,
state.sorted,
state.filtered
).then(res => {
this.setState({
data: res.rows,
pages: res.pages,
loading: false
});
});
}
render() {
const { data, pages, loading } = this.state;
return (
<div>
<ReactTable
columns={[
{
Header: "Name",
accessor: "name"
},
{
Header: "Movement",
accessor: "movement"
},
{
Header: "Equipment",
accessor: "equipments"
},
{
Header: "Channel",
accessor: "channel"
},
{
Header: "Level",
accessor: "skill_level"
},
{
Header: "Duration",
accessor: "duration",
filterable: false
},
{
Header: "Injuries",
accessor: "injuries"
},
{
Header: "Is Substitute",
accessor: "has_video",
Cell: ({ value }) => (value? 'Yes': 'No'),
filterable: false
}
]}
data={data}
pages={pages}
loading={loading}
onFetchData={this.fetchData}
manual
filterable
defaultPageSize={10}
className="-striped -highlight"
/>
</div>
);
}
}
render(<ExerciseList />, document.getElementById('datatable'));
Please refer the link for server-side sorting, pagination and manual filtering within the grid
// Component related to methods for sorting, pagination server side and filtering manual filtering with in the grid
import React from 'react'
import 'react-table/react-table.css'
import ReactTable from 'react-table'
import autoBind from 'react-autobind'
import {filterCaseInsensitive} from '../../helper/commonMethods'
class ServerSideAtomGrid extends React.Component {
super(props)
const userDetails = getUserDetails()
this.state = {
page: 0,
pageSizeOptions: [500, 1000, 2000, 4000],
pageSize: 500,
totalRecords: 0,
nextCursor: '*',
cursorList: [{
page: 0,
cursor: '*'
}],
sortFields: {
field: 'created_dtm',
sort: 'desc'
},
columnData,
}
autoBind(this)
}
handlePageChange (page) {
const pageNumber = (page)
const cursorList = this.state.cursorList
let cusrsorMark = ''
_.each(cursorList, (list) => {
if (list.page === pageNumber) {
cusrsorMark = list.cursor
}
})
this.setState({
nextCursor: cusrsorMark,
page: pageNumber
}, () => this.searchData(cusrsorMark, pageNumber))
}
handleSizePerPageChange (pageSize) {
this.resetData(pageSize)
this.searchData('*', 0)
}
handleSorting = (state, instance) => {
const sorted = state
let field = 'created_dtm'
let sort = 'desc'
sorted && sorted.length > 0 && sorted.map(fld => {
field = fld.id
sort = fld.desc ? 'desc' : 'asc'
})
this.setState({
sortFields: {
field,
sort
}
}, () => this.searchData('*', 0))
}
////
searchData('*', 0) {
//Axios call you cna have
}
filterCaseInsensitive (filter, row) {
const id = filter.pivotId || filter.id
return row[id] ? row[id].toString().toLowerCase().includes(filter.value.toLowerCase()) : true
}
render () {
const {
classes, gridData, gridColumns, defaultFilter, totalRecords,
gridPageSizeOptions, gridPage, gridPages, gridPageSize, gridLoading
} = this.props
return (
<div>
<ReactTable
columns={gridColumns}
data={gridData}
onSortedChange={(state, instance) => {
this.handleSorting(state, instance)
}}
filterable={defaultFilter}
defaultFilterMethod={filterCaseInsensitive}
noDataText="Ops No result found!"
defaultPageSize={this.state.pageSize}
className="-highlight"
style={{height: `${totalRecords < 25 ? '' : `800px`}`, width: '100%', textAlign: 'center'}}
pageText={`Total Count : ${totalRecords.toLocaleString()} Page: `}
loading={gridLoading}
page={this.state.page}
pages={this.state.pages}
showPaginationTop
pageSize={this.state.pageSize}
pageSizeOptions={gthis.state.pageSizeOptions}
minRows={25}
manual
onPageChange={page => {
this.setState({page})
this.handlePageChange(page)
}}
onPageSizeChange={(pageSize, page) => {
this.setState({
page,
pageSize
})
this.props.handleSizePerPageChange(pageSize)
}}
showPageJump={false}
/>
</div>
)
}
}
export default (ServerSideAtomGrid)
My Fiddle: https://jsfiddle.net/gowthamguruju/o9ybxqaj/8/
I have Flask back-end and Angular front-end. My backend working well when I test it via Postman. I send the this kind of data
{
"date": "2018-01-27"
}
#app.route("/schedule", methods=['GET', 'POST'])
def schedule():
cursor = mysql.connection.cursor()
get_date = request.get_json(force = True)
day_name = datetime.datetime.strptime(get_date['date'], '%Y-%m-%d').strftime('%A')
week_number = datetime.datetime.strptime(get_date['date'], '%Y-%m-%d').strftime('%V')
...
But I have problems when I'm trying to send it from Angular.
My service :
#Injectable()
export class RequestService {
constructor(private http:Http) { }
getData(model): Observable<any>{
return this.http.post("http://127.0.0.1:5000/schedule",model)
.map((response:Response)=>{return response.json() });
}
}
My component:
export class CalendarComponent implements OnInit {
public myDatePickerOptions: IMyDpOptions = {
dateFormat: 'yyyy-mm-dd',
openSelectorOnInputClick: true,
satHighlight: true
};
data:any;
public model:any = { jsdate: new Date()};
constructor(private http:RequestService) { }
ngOnInit() {
}
getData(){
this.http.getData(this.model.formatted).subscribe(result => {
this.data = result;
});
console.log(this.model.formatted)
}
the error:
zone.js:2933 POST http://127.0.0.1:5000/schedule 400 (BAD REQUEST)
ERROR Response {_body: "<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final/…object: Extra data: line 1 column 5 (char 4)</p>↵", status: 400, ok: false, statusText: "BAD REQUEST", headers: Headers, …}
And this is structure of this.model:
{date: {…}, jsdate: Sat Jan 27 2018 00:00:00 GMT+0300 (RTZ 2 (зима)), formatted: "2018-01-27", epoc: 1517000400}
What should I send to get a normal reponse?
Use this
this.http.getData({date: this.model.formatted})
And modify your post methot like that
let headers = new Headers();
headers.append('Content-Type', 'application/json');
return this.http.post("http://127.0.0.1:5000/schedule", JSON.stringify(model), {headers: headers})
Angularjs code
var app = angular.module('myApp', []);
app.factory('httpSend', ['$http', '$q', function($http, $q) {
var app = {};
app.sendToServer = function(data) {
$http({
method: "POST",
url: '/report',
data: data,
headers: {
'Content-type': 'application/x-www-form.urlencoded;'
}
}).then(function(response) {
debugger
var result = data;
});
}
app.getfromServer = function() {
var def = $q.defer();
$http.get('/report').then(function(data) {
console.log(data);
def.resolve(data);
}),
function(error) {
def.reject("Failed to get albums");
};
return def.promise;
}
return app;
}]);
app.controller('myCtrl', ['$scope', '$http', 'httpSend', '$filter', function($scope, $http, httpSend, $filter) {
$scope.names = ["ankit patidar", "adhishi ahari", "kritin joshi", "kautilya bharadwaj", "punita ojha", "manvi agarwal", "apeksha purohit", "shipra jain", "mansi nangawat", "praveen soni"];
$scope.data = [];
$scope.names.forEach(function(name) {
$scope.data.push({
name: name,
checkin: "",
checkout: ""
})
});
$scope.login = [];
$scope.check = function(name, doing) {
debugger
name[doing] = new Date();
name[doing] = $filter('date')(name[doing], 'dd-MM-yyyy hh:mm:ss');
$scope.login.push(angular.copy(name));
if (doing == "checkout") {
var q = JSON.stringify($scope.login);
httpSend.sendToServer(q);
}
}
$scope.getData = function() {
httpSend.getfromServer();
}
}]);
`
Python Code
def get(self):
logging.info('get is triggered')
obj = CheckIn.query().fetch()
emp_obj = []
for x in obj:
logging.info('I am inside for loop ')
emp_obj.append({
'name': x.name,
'Check_in': x.inDate,
'check_out': x.outDate
})
logging.info('I am inside emp_obj')
self.response.write(json.dumps(emp_obj))
i need to fetch all the data stored on ndb datastore on front end view thats why i m using http get method but error is showed method not allowed. can u please help e despite using query fetch and showing its response on python ad triggering get method, why error is coming, is there a mistake in control flow or something is missing in my get method, as for now i m able to post nd store data
Change your factory to the following. Don't use the same variable app that you are using for initialising your module for your controller logic.
app.factory('httpSend',['$http', '$q',function($http, $q){
return {
'sendToServer': function(data) {
var def = $q.defer();
$http({
method: "POST",
url: '/report',
data: data,
headers: {
'Content-Type': 'application/json'
}
}).then(function(response) {
debugger
var result = response.data;
def.resolve(result );
});
return def.promise;
},
'getfromServer': function() {
var def = $q.defer();
$http.get('/report').then(function(data) {
console.log(data);
def.resolve(data);
}),
function(error) {
def.reject("Failed to get albums");
};
return def.promise;
}
}
}]);