Using Django I'm getting the following error when making a POST to my API:
The format indicated 'text/plain' had no available deserialization method. Please check your formats and content_types on your Serializer."
I have tried adding the enctype="application/x-www-form-urlencoded to the form but the error is the same. I'm thinking maybe this is a API serializer issues?
Any idea's?
This is the AJAX:
$.ajax({
url: '/api/v1/rewards/campaigns/',
type: 'POST',
dataType: "json",
beforeSend: function (request) {
request.setRequestHeader("X-CSRFToken", $('input[name="csrfmiddlewaretoken"]').val());
},
data: $('#registration').serialize(),
success: function(data, textStatus) {
console.log('success');
},
error: function(errorThrown){
// data = JSON.parse(errorThrown.responseText);
console.log(errorThrown);
}
});
This is the resource it is posting to:
class urlencodeSerializer(Serializer):
formats = ['json', 'jsonp', 'xml', 'yaml', 'html', 'plist', 'urlencode']
content_types = {
'json': 'application/json',
'jsonp': 'text/javascript',
'xml': 'application/xml',
'yaml': 'text/yaml',
'html': 'text/html',
'plist': 'application/x-plist',
'urlencode': 'application/x-www-form-urlencoded',
}
def from_urlencode(self, data, options=None):
""" handles basic formencoded url posts """
qs = dict((k, v if len(v) > 1 else v[0] )
for k, v in urlparse.parse_qs(data).iteritems())
return qs
def to_urlencode(self, content):
pass
class CampaignCreateResource(ModelResource):
class Meta:
queryset = Campaign.objects.all()
resource_name = 'rewards/campaigns'
allowed_methods = ['post', 'get']
serializer = urlencodeSerializer()
validation = FormValidation(form_class=CampaignForm)
Add contentType: 'application/json; charset=UTF-8' to your $.ajax() call to indicate the content type of the request data.
dataType argument specifies the format of the response, not the request!
Related
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
Updated Question:
Wrong redirection of URL in Django. I have this:
views.py.
def graph(request):
if request.method == 'POST' and 'text' in request.POST:
print("testing....")
print(request.POST.get('text'))
name = request.POST.get('text')
context = {
'name': name,
}
print(context)
return render(request, 'StockPrediction/chart.html', context)
else:
return render(request, 'StockPrediction/greet.html')
urls.py
urlpatterns = [
path("", views.greet, name='greet'),
path("index/", views.index, name='Stock Prediction'),
path("prediction/", views.prediction, name='Prediction'),
path("view/", views.graph, name='Graph'),
]
for testing purposes, I m using a print statement. So there is no problem until printing print(context) but the problem is it goes to 'StockPrediction/greet.html' not 'StockPrediction/chart.html'. which I need.
You should use ajax request:
$.ajax({
type: 'POST',
url: 'YOUR VIEW URL',
data: {'row': row, 'text': text},
success: function (data){
DO SOMETHING HERE if VIEW has no errors
})
in your view:
row = request.POST.get('row')
text = request.POST.get('text')
also you should care about crsf-token. Documentation
your can POST it GET it or put it as a variable in your url. here is a post approach:
using jquery :
$.ajax({
url : "/URL/to/view",
type : "POST", // or GET depends on you
data : { text: $text },
async: false,
// handle a successful response
success : function(json) {
// some code to do with response
}
},
// handle a non-successful response
error : function(xhr,errmsg,err) {
$('#results').html("<div class='alert-box alert radius' data-alert>Oops! We have encountered an error: "+errmsg+
" <a href='#' class='close'>×</a></div>"); // add the error to the dom
console.log(xhr.status + ": " + xhr.responseText); // provide a bit more info about the error to the console
}
});
In your view you can get the data as json and return josn as response
import json
def my_view(request):
if request.method == 'POST':
response_data = {} // to return something as json response
text = request.POST['text']
...
return HttpResponse(
json.dumps(response_data),
content_type="application/json"
else:
return HttpResponse(
json.dumps({"nothing to see": "this isn't happening"}),
content_type="application/json"
)
So I am using axios in order to send a JSON request to Django API.
axios({
method: 'post',
url: 'http://127.0.0.1:8000/' + this.state.dataRequestEndPoint,
data: (reqData)
});
Just before the axios call I can see the request:
Object {nvm: "", a: Array(1), b: Array(1), c: Array(1), d: Array(1)}
However, when it gets to Django:
class TargetClass(APIView):
def get(self, request):
Here request is empty:
(Pdb) request.data
<QueryDict: {}>
(Pdb) request.body
b''
def post(self):
pass
What am I doing wrong?
P.S. Tried to send the request with fetch as well:
fetch('http://127.0.0.1:8000/' + this.state.dataRequestEndPoint, {
method: 'POST',
body: reqData,
})
None of it works.
Here is the solution for the problem above. Apparently, axios needs to send parameters:
var reqData = this.state.requestParams
axios({
method: 'post',
url: 'http://127.0.0.1:8000/' + this.state.dataRequestEndPoint,
params: {
'a': reqData['a'],
'b': reqData['b']
}
})
.then(function (response) {
console.log(response)
})
.catch(function (error) {
console.log(error)
});
However, I don't know how good this solution is security-wise.
Totally unclear 404 Ajax error.
var int_page_number = 2;
$.ajax({
type:'GET',
url: '/loadmore/',
data: { 'page_number' : int_page_number},
dataType: 'json',
success: function (data) {
alert(data);
}
});
In the place passing data, I tried both using apostrophe and not around page_number. It's 404 so error may be in frontedn, but anyways I attach django urls.py string just in case :
url(r'^loadmore/(?P<page_number>[0-9]+)/$', views.loadmore),
and views.py function, which is all right:
#api_view(['GET', ])
def loadmore(request,page_number):
answers_to_questions_objects = Question.objects.filter(whom=request.user.profile).filter(answered=True).order_by('-answered_date')
paginator = Paginator(answers_to_questions_objects,10)
current_page = (paginator.page_number)
answers = serializers.serialize('json', current_page)
data = {
'answers': answers
}
return Response(data)`
For your url you should make a call to the url like /loadmore/2/, but you make the call like /loadmore/?page_number=2. So your ajax should be like this:
var int_page_number = 2;
$.ajax({
type:'GET',
url: '/loadmore/' + int_page_number + '/',
success: function (data) {
alert(data);
}
});
I have two different AJAX requests that I want to combine.
The first one gets some html:
def ajax_get_html(request):
if request.is_ajax() and request.method == "POST":
context = {
...
}
return render(request,"my_app/my_template.html", context)
else:
raise Http404
And is used like this:
$.ajax({
type: "POST",
url: ajax_url,
data: {
csrfmiddlewaretoken: "{{ csrf_token }}",
},
success: function(data){
$(my_div).html(data);
}
});
My second one gets some data:
def ajax_get_data(request):
if request.is_ajax() and request.method == "POST":
data = {
"answer": 42,
}
json_data = json.dumps(data)
return HttpResponse(json_data, content_type='application/json')
else:
raise Http404
and is used like this:
$.ajax({
type: "POST",
url: another_ajax_url,
data: {
csrfmiddlewaretoken: "{{ csrf_token }}",
},
success: function(data){
var answer = data.answer;
$("#notification_badge").html(answer);
}
});
How can I combine these to into the same request? I tried adding the result of render to the data in the second view, but json.dumps says it's non serializable.
You can't serialize the output of Django's render because it returns an HttpResponse object, not a string (which is what you want to be able to serialize it).
A good solution is to return your html to the frontend using render_to_string:
...
data = {
"answer": 42,
"html": render_to_string("my_app/my_template.html", context)
}
...