I am creating an online shopping and the users should pay their orders by using a credit card payment. So, I created a sandbox account to test the Braintree API, install the Braintree and make the all configuration as it is shown the python files below. But, as you can notice in figure 3, the card information framework is displayed with only the card lables but there are the fields of the Card number, the Cvv and the expiration date of the card.
Payment/views.py:
import braintree
from django.shortcuts import render, redirect, get_object_or_404
from orders.models import Order
def payment_process(request):
order_id = request.session.get('order_id')
order = get_object_or_404(Order, id=order_id)
if request.method == 'POST':
# retrieve nonce
nonce = request.POST.get('payment_method_nonce', None)
# create and submit transaction
result = braintree.Transaction.sale({
'amount': '{:.2f}'.format(order.get_total_cost()),
'payment_method_nonce': nonce,
'options': {
'submit_for_settlement': True
}
})
if result.is_success:
# mark the order as paid
order.paid = True
# store the unique transaction id
order.braintree_id = result.transaction.id
order.save()
return redirect('payment:done')
else:
return redirect('payment:canceled')
else:
# generate token
client_token = braintree.ClientToken.generate()
return render(request,
'payment/process.html',
{'order': order,
'client_token': client_token})
def payment_done(request):
return render(request, 'payment/done.html')
def payment_canceled(request):
return render(request, 'payment/canceled.html')
After clicking on the Place order button, I was expecting to get a form like the one below but unfortunately, I've got a form without fields.
This is the template that displays the payment form and processes:
{% extends "base.html" %}
{% block title %}Pay by credit card{% endblock %}
{% block content %}
<h1>Pay by credit card</h1>
<form action="." id="payment" method="post">
<label for="card-number">Card Number</label>
<div id="card-number" class="field"></div>
<label for="cvv">CVV</label>
<div id="cvv" class="field"></div>
<label for="expiration-date">Expiration Date</label>
<div id="expiration-date" class="field"></div>
<input type="hidden" id="nonce" name="payment_method_nonce" value="">
{% csrf_token %}
<input type="submit" value="Pay">
</form>
<!-- Load the required client component. -->
<script src="https://js.braintreegateway.com/web/3.29.0/js/client.min.js">
</script>
<!-- Load Hosted Fields component. -->
<script src="https://js.braintreegateway.com/web/3.29.0/js/hostedfields.min.js"></script>
<script>
var form = document.querySelector('#payment');
var submit = document.querySelector('input[type="submit"]');
braintree.client.create({
authorization: '{{ client_token }}'
}, function (clientErr, clientInstance) {
if (clientErr) {
console.error(clientErr);
return;
}
braintree.hostedFields.create({
client: clientInstance,
styles: {
'input': {'font-size': '13px'},
'input.invalid': {'color': 'red'},
'input.valid': {'color': 'green'}
},
fields: {
number: {selector: '#card-number'},
cvv: {selector: '#cvv'},
expirationDate: {selector: '#expiration-date'}
}
}, function (hostedFieldsErr, hostedFieldsInstance) {
if (hostedFieldsErr) {
console.error(hostedFieldsErr);
return;
}
submit.removeAttribute('disabled');
form.addEventListener('submit', function (event) {
event.preventDefault();
hostedFieldsInstance.tokenize(function (tokenizeErr, payload) {
if (tokenizeErr) {
console.error(tokenizeErr);
return;
}
// set nonce to send to the server
document.getElementById('nonce').value = payload.nonce;
// submit form
document.getElementById('payment').submit();
});
}, false);
});
});
</script>
{% endblock %}
How can I get an "empty cart information" and not even have the cards fields while I have placed an order?
Thanks
Related
I am trying to get the id of a model object of django from the template using ajax. But I cannot get the exact value of data in the views.py.I am getting a None value for id in views. Where I have done wrong? Here is my code
Views.py:
def is_ajax(request):
return request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest'
def home(request):
return render(request, 'home/home.html')
def index(request):
# If you have passed any data through the 'data' property
#you can get it here, according to the method used.
##if is_ajax(request=request):
id = request.GET.get('data')
msg = testing.objects.exclude(id = id).first()
# Note that we are passing the 'ajax_comments.html' template.
#return render(request, 'practice.html', {'text': msg, 'id':id})
##else:
##msg = testing.objects.last()
return render(request, 'practice.html', {'text': msg, 'id': id} )
#comments = Comment.objects.all.first()
#return render(request, 'practice.html', {'comments': comments})
Template:
{% extends 'base.html'%}
{%block head %} {%endblock%}
{%block navbar %} {% endblock %}
{%block navsmall %} {% endblock %}
{% block header%}
{% endblock %}
{% block firstgrid%}
{%endblock%}
{%block secondgrid%}
<div id = 'myTest'>
{{text.text}} <br> {{id}}
<button class = "asd" value="{{text.td}}">Button</button>
</div>
<script>
$(".asd").click(function(e){
e.preventDefault();
var id = $(this).val();
$.ajax({
method: 'GET', // defaults to GET. Set POST if you like, but be aware of the CSRF token submission too!
url: "{% url 'practice' %}", // submit to the same url
data: {'data': id}, // pass here any data to the server. You can omit it.
success: function(data) {
// This function will run when server returns data
$('#my-Test').replaceWith(data);
alert('ok');
console.log(id);
},
error: (error) => {
console.log('error');
}
});
});
</script>
{%endblock%}
{%block footer%}
{%endblock%}
In views I am getting None value in id
I have a django application that displays a few charts generated using plotly.
This is my views.py file
def home(request):
const_list = pd.read_csv('./const.csv').Const.unique()
party_list = pd.read_csv('./part_list.csv').abbr.unique()
all_list = pd.read_csv('./all_list.csv').All.unique()
chked=request.POST.get('chk', '')
print(chked)
if chked == 'true':
part_bargraph = main_graph(all_list, len(const_list))
else:
part_bargraph = main_graph(part_list, len(const_list))
context = {'main_graph': part_bargraph, 'const': const_list}
print(context)
return render(request, 'home.html', context)
The main_graph is a function that takes a list and an int value as parameters and generates a plotly graph. This graph is then returned as a json object using the plotly.io.to_json method.
I want to display this graph in an HTML template. This is what I am doing right now
<form method='post'>
{% csrf_token %}
<div class="switch">
<input id='chk' type="checkbox" class="switch-input" />
<label for="chk" class="switch-label">Switch</label>
</div>
</form>
<div class="main_graph" id='main_graph'></div>
<script>
Plotly.newPlot("main_graph", {{ main_graph | safe }})
$(document).on('click', '#chk', function (e) {
$.ajax({
type: 'POST',
url: '/home',
data: {
chk: $('#chk').prop('checked'),
csrfmiddlewaretoken: $('input[name=csrfmiddlewaretoken]').val()
},
success: function (data) {
Plotly.newPlot("main_graph", {{ main_graph | safe }})
}
});
})
</script>
When I print the context after toggling the button, I can see that the graph has changed. But I am not able to display that in the template.
What am I doing wrong?
Thanks in advance
My program must update table "idlist" in python after the item was selected from drop down suggestions in js. User selects the item, after that POST request in python adds it to the "idlist" table.
As I run the program I get the following error message:
I am grateful for your ideas and suggestions:
Here is my python code:
def search():
"""Search for books that match query"""
if request.method == "GET":
if not request.args.get("q"):
return render_template("adjust.html")
else:
q = request.args.get("q") + "%"
books = db.execute("SELECT Title, Author FROM book WHERE Title LIKE :q OR Author LIKE :q", q=q)
return jsonify(books)
if request.method == "POST" and request.form.get("title"):
Title = request.form.get("title")
insert_book = db.execute("INSERT INTO idlist (id,Title1, Status) VALUES (:id, :Title1, :Status)", id=session["user_id"], Title1=Title, Status="Not started")
return redirect("/")
return render_template("adjust.html")
Here is html:
{% extends "layout.html" %}
{% block title %}
Add your Book
{% endblock %}
{% block main %}
<form action="/adjust" method="POST">
<div class="form-group">
<p>Choose your Book</p>
<label class="sr-only" for="q">Title, Author</label>
<input class="form-control" id="q" placeholder="Title, Author" name="title" type="text" autocomplete="off" />
</div>
<button class="btn btn-primary" type="submit">Add</button>
</form>
{% endblock %}
Here is js:
function configure()
{
// Configure typeahead
$("#q").typeahead({
highlight: false,
minLength: 1
},
{
display: function(suggestion) { return suggestion.Title; },
limit: 10,
source: search,
templates: {
suggestion: Handlebars.compile(
"<div>"+
"{{Title}}, {{Author}}" +
"</div>"
)
}
});
// Give focus to text box
$("#q").focus();
}
// Search database for typeahead's suggestions
function search(query, syncResults, asyncResults)
{
// Get places matching query (asynchronously)
let parameters = {
q: query
};
$.getJSON("/adjust", parameters, function(data, textStatus, jqXHR) {
// Call typeahead's callback with search results (Author Title)
asyncResults(data);
});
}
$(document).ready(function() {
configure();
});
Don't use Ajax to Add new book it will make user confused because he don't know if it was added to the idlist or not, use the Form POST instead.
in script.js remove the following block
$("#q").on('typeahead:selected', function a(eventObject, suggestion, name) {
...
...
});
and to add selected item to the input form, replace
display: function(suggestion) { return null; },
with
display: function(suggestion) { return suggestion.Title; },
to make form POST, in adjust.html replace
<form action="/adjust">
....
<input class="form-control" id="q" placeholder="Title, Author" type="text"/>
with
<form action="/addbook" method="POST">
....
<input class="form-control" id="q" placeholder="Title, Author" name="title" type="text" autocomplete="off" />
And the addBook() method
#app.route("/addbook", methods=["GET", "POST"])
def addbook():
"""Add selected book"""
if request.method == "POST" and request.form.get("title"):
Title = request.form.get("title")
insert_book = db.execute("INSERT INTO idlist (id,Title1, Status) VALUES (:id, :Title1, :Status)", id=session["user_id"], Title1=Title, Status="Not started")
return redirect("/")
# no "title" in the form, return to Add new book page
return redirect("/adjust")
I got values of dropdown list which is expense.id and expense_type. In database I look for expense object which has id==expense.id sent by ajax in order to update its type (expense_type). So I need to send both expense.id and expense.type to sever using ajax. I dont know how to perform in jQuery as well as html. Below is my code I got error which is "Not Found: /polls/17/project_detail/ajax/update_form/"
<form action="/ajax/update_form/" method="POST" id="selection-form">
{% csrf_token %}
<select id="select_dropdown">
{% for expense in expenses %}
{% if project.id and expense.city %}
<option value="{{expense.id}}" selected="selected">{{expense.expense_type}}</option>
{% else %}
<option value="{{expense.id}}">{{expense.expense_type}}</option>
{% endif %}
{% endfor %}
</select>
<td><input type="submit" value="Save"></td>
</form>
=====js====
$('#selection-form').on('submit', function(event) {
event.preventDefault();
console.log("form_submitted");
create_post();
});
function create_post(){
console.log("update fucntion is working!");
var value = $("#select_dropdown").find(":selected").val();
var text = $("#select_dropdown option:selected").text();
$.ajax({
//url: "{% url 'update_form' %}",
url: "ajax/update_form/",
method: "POST",
data: {
"value": value,
"text": text,
//"pro_expense": pro_expense,
//"id": valueSelected,
csrfmiddlewaretoken: '{{ csrf_token }}',
},
//dataType: "json",
success: function(data){
console.log(data);
},
error: function(error_data){
console.log("error")
console.log(error_data)
}
});
return false;
};
====views.py=====
#csrf_exempt
def update_form(request):
if request.method == "POST" and request.is_ajax():
value = request.POST.get('value')
text = request.POST.get('text')
expense = Expense.objects.get(pk = value)
expense.expense_type = text
expense.save()
return HttpResponse({"result": "success"}, content_type="application/json")
===urls.py===
url(r'^(?P<project_id>[0-9]+)/project_detail/$', views.project_detail, name='project_detail'),
url(r'^ajax/update_form/$', views.update_form, name = 'update_form'),
error is "Not Found: /polls/17/project_detail/ajax/update_form/". please help. Any help will be highly appreciated!!
I want to hide form if user already pushed on the button. I tried to use a bit of JS code, it works well, but after refreshing page, button on form stay valid. It not a huge surprise for me)) I want hide form using Django templates, but it is not so easy as I thought.
my html :
<div class="who_come">
<p>Who come : </p>
{% for u in who_come %}
{%if u.visiter.username != request.user.username %}
<form class="form-inline" role="form" method="post" id="joinToEventForm">
{% csrf_token %}
<p align="left"><b ><button type="submit">I want join</button></b></p></b></p>
</form>
{% endif %}
{% endfor %}
<div id="who_come_links">
{% for u in who_come reversed %}
<p>{{u.visiter.username}}</p>
{% endfor %}
</div>
<script>
$('#joinToEventForm').submit(function() {
$(this).find("button[type='submit']").prop('disabled',true);
});
</script>
<script>
$('#joinToEventForm').on('submit', function(event){
event.preventDefault();
console.log("form submitted!") // sanity check
$.ajax({
type:'POST',
data:{
action: 'joinEvent',
csrfmiddlewaretoken:'{{ csrf_token }}'
},
success : function (data) {
//console.log(data);
var usernames = JSON.parse(data);
var html_str = '';
for (var i=0; i < usernames.length; i++) {
html_str += '<p>' + usernames[i] + '</p>';
}
$('#who_come_links').html(html_str);
}
});
});
</script>
</div>
my model :
class WhoComeOnEvent(models.Model):
visiter = models.ForeignKey(User, related_name='WhoComeOnEvent')
which_event = models.ForeignKey(Topic, related_name='WhoComeOnEvent')
in this place :
<p>Who come : </p>
{% for u in who_come %}
{%if u.visiter.username != request.user.username %}
<form class="form-inline" role="form" method="post" id="joinToEventForm">
{% csrf_token %}
<p align="left"><b ><button type="submit">I want join</button></b></p></b></p>
</form>
{% endif %}
{% endfor %}
i tried to check who already joined to event and if user that do request same that user in database table, then hide form. But this code doesn't work. It hide form no matter if user exist in db table or not. Second part is that has no connection to current event. Suppose django template that hide form in my case will work. It will check only row in table but it will ignore current it event or it different event (not sure, but i'm afraid of it).
my view :
def p(request, pk):
user = request.user
topic = get_object_or_404(Topic, pk=pk)
post = get_object_or_404(Post, pk=pk)
comment = Comments.objects.filter(pk=pk)
who_come = WhoComeOnEvent.objects.filter(which_event=topic.id)
if request.is_ajax() and request.POST.get('action') == 'joinEvent':
who_come_obj = WhoComeOnEvent.objects.create(
visiter=user,
which_event=post.topic
)
visitors_usernames = []
for w in who_come:
visitors_usernames.append(w.visiter.username)
return HttpResponse(json.dumps(visitors_usernames))
if request.method == 'POST':
form = CustomCommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.post = post
comment.creator = user
comment = Comments.objects.create(
body=form.cleaned_data.get('body'),
creator=user,
post=post
)
return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
# return render(request, 'post.html', {'post': post, 'topic': topic, 'comment': comment,
# 'form': form, 'who_come': who_come})
else:
form = CustomCommentForm()
return render(request, 'post.html', {'post': post, 'topic': topic, 'comment': comment,
'form': form, 'who_come': who_come})
Solution:
I found more elegant solution, just adding .distinct('visitor') to my who_come queryset.
If someone will read it question and found my solution helpful, notice, that objects still creating to the databese and it doesn't unique!