Adding extra parameters when sending request with django and stripe - python

I've been trying to send extra parameters when submiting the stripe button, which is integrated in my Django application, but I cannot make it work.
So far, I have this:
views.py
stripe.api_key = "XXXX"
class StripeApi(View):
#staticmethod
def post(request):
a = request.body
event_json = json.dumps(a)
print a
return HttpResponse(
event_json, content_type="application/x-javascript-config")
urls.py
urlpatterns = [
url(r'^stripe/', ApiViews.StripeApi.as_view()),
]
index.html
<form action="" method="POST">
<input type="text" name="extraParam2" value="55555fghjkldfgdgfasdfghhjjj"> <!-- here, I tried to add extraParam2 -->
<script
src="https://checkout.stripe.com/checkout.js" class="stripe-button"
data-key="XXXX"
data-amount="2000"
data-name="Demo Site"
data-description="2 widgets ($20.00)"
data-image="/128x128.png"
data-locale="auto">
</script>
</form>
Any hints on this, please ?
//EDIT:
I tried to integrate what Ywain gave me into my app and I get "POST /stripe/ HTTP/1.1" 405 0 in console after completing and sending the form. What do I do wrong ?
views.py
class StripeApi(View):
#staticmethod
def index(request):
return HttpResponse(request, 'index.html', {
'stripe_pub_key': settings.STRIPE_PUBLISHABLE_KEY},
content_type="application/x-javascript-config")
#staticmethod
def charge(request):
charge = stripe.Charge.create(
amount=2000,
currency='usd',
source=request.POST['stripeToken'],
description='Charge for {}'.format(request.POST['stripeEmail'])
)
return HttpResponse(request, 'stripe.html', {'charge_id': charge.id,
'extra_param': request.POST['extraParam2']},
content_type="application/x-javascript-config")
settings.py:
'''stripe'''
STRIPE_SECRET_KEY = 'sk_test_secret',
STRIPE_PUBLISHABLE_KEY = 'pk_test_secret'
stripe.api_key = STRIPE_SECRET_KEY
urls.py
...
url(r'^stripe/', ApiViews.StripeApi.as_view()),
index.html
<form action="/stripe/" method="POST">
<input type="text" name="extraParam2" value="Test extraParam">
<script
src="https://checkout.stripe.com/checkout.js" class="stripe-button"
data-key="pk_test_secret"
data-image="https://stripe.com/img/documentation/checkout/marketplace.png"
data-name="Stripe.com"
data-description="2 widgets"
data-amount="2000"
data-locale="auto">
</script>
</form>
stripe.html
{% extends "base_site.html" %}
{% block content %}
<pre>
Charge ID: {{ charge_id }}
Extra param: {{ extra_param }}
</pre>
{% endblock %}

Here is a minimal Django app that illustrates how to use Stripe Checkout and use the resulting token to create a charge, as well as pass an extra parameter along:
django-stripe.py
import sys
from django.conf import settings
from django.conf.urls import url
from django.core.management import execute_from_command_line
from django.shortcuts import render
from django.views.generic import View
import stripe
settings.configure(
DEBUG=True,
ROOT_URLCONF=sys.modules[__name__],
TEMPLATE_DIRS=['.'],
STRIPE_SECRET_KEY='sk_test_...',
STRIPE_PUBLISHABLE_KEY='pk_test_...'
)
stripe.api_key = settings.STRIPE_SECRET_KEY
class StripeView(View):
#staticmethod
def get(request):
return render(request, 'index.html',
{
'stripe_pub_key': settings.STRIPE_PUBLISHABLE_KEY
})
#staticmethod
def post(request):
charge = stripe.Charge.create(
amount=2000,
currency="usd",
source=request.POST['stripeToken'],
description="Charge for {}".format(request.POST['stripeEmail'])
)
return render(request, 'charge.html',
{
'charge_id': charge.id,
'extra_param': request.POST['extraParam2']
})
urlpatterns = [
url(r'^stripe/', StripeView.as_view()),
]
if __name__ == "__main__":
execute_from_command_line(sys.argv)
index.html
<form action="" method="POST">
{% csrf_token %}
<input type="text" name="extraParam2" value="55555fghjkldfgdgfasdfghhjjj">
<script
src="https://checkout.stripe.com/checkout.js" class="stripe-button"
data-key="{{ stripe_pub_key }}"
data-image="https://stripe.com/img/documentation/checkout/marketplace.png"
data-name="Stripe.com"
data-description="2 widgets"
data-amount="2000"
data-locale="auto">
</script>
</form>
charge.html
<pre>
Charge ID: {{ charge_id }}
Extra param: {{ extra_param }}
</pre>
You can test it by pasting your Stripe API keys (in the STRIPE_SECRET_KEY and STRIPE_PUBLISHABLE_KEY arguments of the settings.configure() function call), starting the app with python django-stripe.py runserver, and pointing your web browser to http://localhost:8000/stripe.
Basically, index.html contains the Checkout form as well as your extra parameter. The form is submitted to the same page (the action attribute of the <form> tag is empty), and is handled by the post() method of the StripeView class. The method creates an actual charge with Stripe's API, and passes the resulting charge ID along with your extra parameter to the charge.html template.

The stripe page mentions a 'custom' option for using a stripe button, this is probably what you want, you can add extra values to your button:
https://stripe.com/docs/checkout#integration-custom
<script src="https://checkout.stripe.com/checkout.js"></script>
<button id="customButton">Purchase</button>
<script>
var handler = StripeCheckout.configure({
key: 'pk_test_6pRNASCoBOKtIshFeQd4XMUh',
image: '/img/documentation/checkout/marketplace.png',
locale: 'auto',
token: function(token) {
// Use the token to create the charge with a server-side script.
// You can access the token ID with `token.id`
}
});
$('#customButton').on('click', function(e) {
// Open Checkout with further options
handler.open({
name: 'Stripe.com',
description: '2 widgets',
amount: 2000
});
e.preventDefault();
});
// Close Checkout on page navigation
$(window).on('popstate', function() {
handler.close();
});
</script>

Related

Form post request running wrong view method on Django

I'm trying to clone the Instagram web page using Django(version-3.1).
My Django project has an app called 'post'.
One of its template I have a form which is posting a comment to a post. The form post request should call the path('add_comment/',views.add_comment,name='add_comment'), but It's calling path('<slug:slug>/',views.post_details,name='post_details'), instead. And raising DoesNotExist at /post/add_comment error. I added print() statement at the beginning of both add_comment() and post_details() methods to find out which is running when the request is made. I have no idea what I have done wrong.
The project GitHub link - https://github.com/mirasel/Instagram_Clone
the post_details.html template is -
{% extends 'base.html' %}
{% load static %}
{% block title %} post {% endblock %}
{% block profilephoto %} {{ propic.url }} {% endblock %}
{% block body %}
<div>
<div>
<img src="{{post.image.url}}" alt="post" height="250px" width="250px">
</div>
<div>
<a href="{% url 'instagram:profile' post.uploader %}">
<img src="{{uploader.profile_pic.url}}" alt="{{uploader}}" style="border-radius: 50%;" height="24px" width="24px">
{{ post.uploader }}
</a><br>
<p>{{ post.date_published.date }}</p>
</div>
<div>
<p>{{ post.caption }}</p>
</div>
<div>
<form action="{% url 'post:add_comment' %}" id="comment_form" method="POST">
{% csrf_token %}
<textarea name="comment" id="comment" cols="30" rows="1" placeholder="Write a comment..."></textarea>
<input type="hidden" name="slug" id="slug" value="{{post.slug}}">
<!-- <input type="submit" style="display: none;" name="submit"> -->
</form>
<script>
$(function(){
$("#comment").keypress(function (e) {
if(e.which == 13 && !e.shiftKey) {
$(this).closest("form").submit();
e.preventDefault();
}
});
});
</script>
{% endblock %}
the views.py -
from django.shortcuts import render,redirect
from instagram.views import get_nav_propic,get_profile_details
from .models import UserPost,PostComment,PostLike
from django.http import JsonResponse
def get_post_likes(post):
likes = PostLike.objects.filter(post=post)
total_likes = len(likes)
likers = []
for l in likes:
likers.append(get_profile_details(l.liker))
return {'likers':likers,'total_likes':total_likes}
def get_post_comments(post):
comments = PostComment.objects.filter(post=post)
total_comments = len(comments)
commenter = []
comment = []
for c in comments:
commenter.append(get_profile_details(c.commenter))
comment.append(c.comment)
postcomment = zip(commenter,comment)
return {'post_comment':postcomment,'total_comments':total_comments}
def upload_post(request):
if request.method == 'POST':
image = request.FILES['post_img']
caption = request.POST['caption']
uploader = request.user
UserPost.objects.create(uploader=uploader,image=image,caption=caption)
return redirect('instagram:feed')
else:
context = {
'propic' : get_nav_propic(request.user)
}
return render(request,'post/upload_post.html',context)
def post_details(request,slug):
print('I am here in post details')
post = UserPost.objects.get(slug=slug)
context = {
'propic' : get_nav_propic(request.user),
'post' : post,
'uploader' : get_profile_details(post.uploader),
'LIKES' : get_post_likes(post),
'COMMENTS' : get_post_comments(post),
}
return render(request,'post/post_details.html',context)
def add_comment(request):
print('I am here in add comment')
if request.method == 'POST':
post_slug = request.POST.get('slug')
post = UserPost.objects.get(slug=post_slug)
user = request.user
comment = request.POST.get('comment')
PostComment.objects.create(post=post,commenter=user,comment=comment)
return redirect('post:post_details',slug=post_slug)
the urls.py -
from django.urls import path
from . import views
app_name='post'
urlpatterns = [
path('upload_post/',views.upload_post,name='upload_post'),
path('<slug:slug>/',views.post_details,name='post_details'),
path('add_comment/',views.add_comment,name='add_comment'),
]
The error - Error page
Solved
I had to make the URL path of add_comment as following-
#previous one
path('add_comment/',views.add_comment,name='add_comment'),
#modified one
path('comment/add_comment/',views.add_comment,name='add_comment'),
This is because the pattern for the slug URL and add comment URL were similar.
Because Django will process the urlpatterns sequentially, from docs:
Django runs through each URL pattern, in order, and stops at the first
one that matches the requested URL, matching against path_info.
And '/add_comment' is a valid slug <slug:slug>, so post_details will be called.
So you should keep the definition of the most generic url patterns at last:
urlpatterns = [
path('upload_post/',views.upload_post,name='upload_post'),
path('add_comment/',views.add_comment,name='add_comment'),
path('<slug:slug>/',views.post_details,name='post_details'),
]
Hopefully this will work for you.

How do I display the result on the current page? Django, Ajax

On the main page I have a text box. When I type text into it, after clicking the button I want to display that text below.
With ajax I get the text entered and pass it to views.py.
When rendering, the result I need is displayed on /localhost:8000/vk_u/
How do I display the result on the current page (localhost: 8000/)?
Thanks
//forms.py
from django import forms
from .models import *
class VK_LINK_Form(forms.Form):
enter_link = forms.CharField(widget = forms.TextInput(attrs={'id':'link_vk_enter'}))
//urls.py
from django.urls import path, include
from . import views
from django.http import HttpResponse
urlpatterns = [
path('', views.index, name = 'index'),
path('vk_u/', views.vk_u, name = 'vk_u'),
]
//js
$(document).on('submit','#vkht_form', function(e){
e.preventDefault();
var link_post_input = $(document.getElementById("link_vk_enter")).val()
$.ajax({
type: 'POST',
url: '/vk_u/',
data:{
link_post_input: link_post_input,
csrfmiddlewaretoken:$('input[name=csrfmiddlewaretoken]').val()
},
});
});
]
//views.py
def vk_u(request):
link_post_input = request.POST.get('link_post_input')
return render(request, "mainApp/homePage.html", {"link_post_input": link_post_input,})
<!-- html -->
<body>
<div>
<form action="" method="GET" id="vkht_form">
{% csrf_token %}
{{ form }}
text: {{ text_post_input }}
<input type="submit" value="CLICK">
</form>
</div>
</body>

Django : SQLite Database is Locked when I build like feature on my home page

I am implementing Like functionality in Web application. Idea is Simple to List number of Post(Blogs) on Home page and Add a Like Button to each post(Blog). It works fine when I build it with normal
<form action='{% url target %}' method='POST'>
But when I implemented this with AJAX call It only allows me to like or dislike a particular post(blog) a single time.i.e One I liked a Post for first time it works, also when I dislike the same Post It works fine, But when I again Like that Post it throws an django.db.utils.OperationalError: database is locked
Also, when I like same post multiple(4 to 5) times it respond in a weird way. I goes in Loop of liking and dislikig post.
like_section.html
<form id="like-form{{ post.id }}">
{% csrf_token %}
<button type="submit" id="{{ post.id }}btn" name="like" value="{{ post.id }}" class="btn upvote">Like</button>
<script type="text/javascript">
{% for like in post.likes.all %}
{% if like != user %}
dislikingPost("{{ post.id }}btn");
{% else %}
likingPost("{{ post.id }}btn");
{% endif %}
{% endfor %}
$(document).ready(function(event){
$(document).on('click', '#{{ post.id }}btn', function(event){
event.preventDefault();
pk = $(this).attr('value');
$.ajax({
type: 'POST',
url: '{% url "like_post" %}',
data: {
'id': pk,
'csrfmiddlewaretoken': '{{ csrf_token }}'
},
success:function(response){
$('#like-form{{ post.id }}').html(response['form'])
// $('#{{ post.id }}btn').style.color = 'green';
}, error: function(er, e){
console.log(er.responseText);
}
});
});
});
</script>
</form>
views.py:
def like_post(request):
all_posts = Posts.objects.all()
print("Insisde Like Post")
print('ID coming from form is', request.POST.get('id'))
post = get_object_or_404(Posts, id=request.POST.get('id')) # for AJAX call
context = {
'all_posts': all_posts,
'post': post
}
if post.likes.filter(id=request.user.id).exists():
post.likes.remove(request.user) # Liking The Post
print("DisLiking the post")
else:
post.likes.add(request.user)
print("Liking the post")
if request.is_ajax():
print('Hey its an AJAX calls') # TEsting AJAX request
html = render_to_string('like_section.html', context, request=request)
return JsonResponse({'form': html})
Note:
1. I am beginner in AJAX.
2. I know SQLite can not handle redundant calls, But why it was working before without AJAX calls.
3. I am not providing models.py and complete template of home page and I don't think they are required.
The Problem was not with the Django code. It was ajax call which was triggering Database more then one time on a single Button Click.
Adding event.stopImmediatePropagation(); below event.preventDefault(); in ajax call works perfect

Django Ajax Comment System

I want to create a comment system with using Ajax. My main purpose is getting new comments in my page without page refreshing. I add some js code to my HTML file but it didn't work. Where are my mistakes and what should I do?
views.py
...
def post_detail(request, pk, ):
post = get_object_or_404(Post, pk=pk)
form = CommentForm(request.POST or None)
if form.is_valid():
comment = form.save(commit=False)
comment.post = post
comment.save()
return redirect('post_detail', pk=post.pk)
context = {
'post': post,
'form': form,
}
return render(request, 'blog/post_detail.html', context)
comments.html
{% load crispy_forms_tags %}
{% load static %}
<hr>
<form method="POST" style="width: 50%; margin-left: 20px" id="comment_form">
{% csrf_token %}
{{ form|crispy }}
<input type="submit" class="btn btn-info" value="Yorum Ekle" style="margin-left: 20px">
</form>
<script type="text/javascript" src="{% static 'js/jquery-1.11.1.min.js' %}"></script>
<script type="text/javascript">
$(document).on('submit', '#comment_form', function (e) {
e.preventDefault();
$.ajax({
type: 'POST',
url: 'http://127.0.0.1:8000/post/12/',
data: {
name: $('#name').val(),
content: $('#content').val(),
created_date: $('#created_date').val(),
post: $('#post').val(),
csrfToken: $('input[name=csrfmiddlewaretoken]').val()
},
success: function () {
alert("YEAH! It works!");
}
}
)
})
</script>
post_detail.html
...
{% include 'blog/comment.html' %}
<hr>
{% for comment in post.comments.all %}
<h4>{{ comment.name }} | <small>{{ comment.created_date|timesince }} önce</small></h4>
<p>{{ comment.content|linebreaks }}</p>
{% endfor %}
urls.py
...
url(r'^post/(?P<pk>\d+)/$', views.post_detail, name='post_detail'),
When I click comment button there is no action. But when I look inspect elements, when I click button it shows Status code:403
Note: I get "YEAH! It works!" alert
You need to return a JsonResponse or a partial template in post_detail method so that you can use these data in ajax success function. I have created a django app for commenting system using ajax response for preventing page refresh. If you are interested Here the package repo
The success function takes an argument, which is the data sent back by the server.
Update your code like this:
success: function (result) {
alert("YEAH! It works!");
}

Django view return value with AJAX

I am working with Django and AJAX,
I have a template where people can select an option and then click a submit button. The button fires an Ajax function that sends the data to my view where it is processed and should return a value back to the template.
The issue is when the post goes through, it hits the view, and nothing is returned to the template, I am not sure if this is because the view isn't getting any data, but it isn't firing any of my conditional statements, so it acts like its working but doesn't return anything.
My HTML form:
<form method="POST" id="buy_form" name="buy_form" action="{% url 'manage:buy' %}">
{% csrf_token %}
<div class="buy_top_section">
<div class="width">
<div class="spacing">
<h3 class="sell_title">How much do you want to sell?</h3>
<input type="text" id="amount" class="buy_input_top" maxlength="10" name="amount" type="number" required>
<select id="selected" class="buy_selection" name="wanted">
<option value="generate_b">BTC</option>
<option value="generate_e">ETH</option>
<option value="generate_l">LTC</option>
</select>
</div>
<span class="float_clear"></span>
<button id='generate' type="submit" value="currency_details" class="custom_button"l">Generate
</button>
</div>
</div>
</form>
<!-- What needs to be returned from thew view -->
<h1>{{ address }}</h1>
My AJAX
$(document).on('submit', '#buy_form', function (e) {
e.preventDefault()
$.ajax({
type: 'POST',
url:'/manage/buy/',
data:{
currency:$('selected').val(),
amount:$('#amount').val(),
csrfmiddlewaretoken:$('input[name=csrfmiddlewaretoken]').val()
},
success: function (){
}
})
});
My Django View
def buy_corsair(request):
if request.method == 'POST':
if request.POST.get('wanted') == 'generate_b':
# Get the amount entered
amount = request.POST.get('amount')
# Generate a new B address
new_b_address = client.create_address(b_account_id)['address']
# Point the address at the user
request.user.user_address.b_address = new_b_address
# Save address to current user
request.user.user_address.save()
# Pass the address to the template
context = {'address': new_b_address}
return render(request, context)
urls.py
urlpatterns = [
# Buy Page
path('buy/', views.buy_corsair, name='buy'),
]
Ajax requests run in background, django render function render a template to body, so you can not render this way. You could like this;
dont forget include
from django.http import HttpResponse
def buy_corsair(request):
if request.method == 'POST':
if request.POST.get('wanted') == 'generate_b':
# Get the amount entered
amount = request.POST.get('amount')
# Generate a new B address
new_b_address = client.create_address(b_account_id)['address']
# Point the address at the user
request.user.user_address.b_address = new_b_address
# Save address to current user
request.user.user_address.save()
# Pass the address to the template
return HttpResponse(new_b_address)
in your js;
$.ajax({
type: 'POST',
url:'/manage/buy/',
data:{
currency:$('selected').val(),
amount:$('#amount').val(),
'csrfmiddlewaretoken': "{{ csrf_token }}"
},
success: function (data){
$('h1').html(data);
}
})
});
in your Django view
import json
from django.http import HttpResponse
def buy_corsair(request):
if request.method == 'POST':
if request.POST.get('wanted') == 'generate_b':
# Get the amount entered
amount = request.POST.get('amount')
# Generate a new B address
new_b_address = client.create_address(b_account_id)['address']
# Point the address at the user
request.user.user_address.b_address = new_b_address
# Save address to current user
request.user.user_address.save()
# Pass the address to the template
context = {'address': new_b_address}
return HttpResponse(json.dumps(context))
in your js
$.ajax({
type: 'POST',
url:'/manage/buy/',
data:{
currency:$('selected').val(),
amount:$('#amount').val(),
csrfmiddlewaretoken:$('input[name=csrfmiddlewaretoken]').val()
},
success: function (response){
console.log(response);
//access the value and print it in console//
var obj=JSON.parse(response)["address"];
alert(obj);
}
})
});

Categories

Resources