Django Braintree Integration - javascript

I would like to integrate Braintree payment into my website. I know there are many mistakes in my code as I'm learning. Currently I am redirected to the Failed http page as the payment doesn't go through. How can I implement the payment on the Cart page? Thank you.
views.py (Cart app)
def cart_detail(request, total=0, cart_items = None):
try:
cart = Cart.objects.get(cart_id=_cart_id(request))
cart_items = CartItem.objects.filter(cart=cart, active=True)
for cart_item in cart_items:
total += (cart_item.service.price)
except ObjectDoesNotExist:
pass
gateway = braintree.BraintreeGateway(
braintree.Configuration(
braintree.Environment.Sandbox,
merchant_id="",
public_key="",
private_key=""
)
)
braintree_total = int(total)
#print(braintree_total)
if request.method == 'GET':
client_token = gateway.client_token.generate()
else: # for when the method is POST
print(request.POST)
result = gateway.transaction.sale({
'amount': braintree_total,
'payment_method_nonce': request.POST['payment_method_nonce'],
'options': {
"submit_for_settlement": True
}
})
if result.is_success or result.transaction:
return HttpResponse('Done')
return HttpResponse('Failed')
return render(request, 'cart.html', dict(cart_items = cart_items, total = total, client_token = client_token))
cart.html (Cart app)
<div class="col-12 col-sm-12 col-md-12 col-lg-6 text-center">
<table class="table my_custom_table">
<thead class="my_custom_thead">
<tr>
<th>
Checkout
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
Please review your shopping cart items before proceeding with the order payment.
</td>
</tr>
<tr>
<td class="text-left">
Your total is: <strong>£{{ total }}</strong>
</td>
</tr>
</tbody>
</table>
<div class="mx-auto">
<form id="payment-form" method="post" action="{% url 'cart:cart_detail' %}">
{% csrf_token %}
<div id="bt-dropin"></div>
<input type="hidden" id="nonce" name="payment_method_nonce" />
<button class="btn btn-primary btn-block" type="submit" id="submit-button"><span>Test Transaction</span></button>
</form>
Continue Shopping
</div>
</div>
</div>
<br>
{% endif %}
<script src="https://js.braintreegateway.com/web/dropin/1.13.0/js/dropin.min.js"></script>
<script>
var button = document.querySelector('#submit-button');
var client_token = '{{ client_token }}';
braintree.dropin.create({
authorization: client_token,
container: '#bt-dropin',
paypal: {
flow: 'vault'
}
}, function (createErr, instance) {
form.addEventListener('submit', function (event) {
event.preventDefault();
instance.requestPaymentMethod(function (err, payload) {
if (err) {
console.log('Error', err);
return;
}
// Add the nonce to the form and submit
document.querySelector('#nonce').value = payload.nonce;
form.submit();
});
});
});
</script>
{% endblock %}
Thank you for your help.

Related

updating flask app with data retrieved from Ajax without updating the application

I have a simple application developed using flask. In one of the html, to avoid excessive refresh because a reload is expensive, I am using ajax to collect the inputs passed by the user and sending that to the endpoint in flask for use. This works, the data is passed and the values are used, the problem is that the values are not updated on the frontend application.
These are the inputs I collect from the user:
<div class="col-sm-4">
<h1 style="font-size: 1.5rem">Choose Dates</h1>
<div style="border: 1px solid black; padding: 1%">
<input
type="date"
id="start-date"
name="start-date"
value="{{default_start}}" />
<label for="date">to</label>
<input
type="date"
id="end-date"
name="end-date"
value="{{default_end}}"/>
<input
class="btn btn-primary"
type="submit"
value="submit"
onclick="get_dates();" />
</div>
In the same template I use those inputs and process data to a bootstrap table:
<!-- Tables -->
<div style="padding-top: 2%">
<table class="table">
<thead class="table-dark">
<tr>
{% for channel in channels %}
<th scope="col">{{channel}}</th>
{% endfor %}
</tr>
</thead>
<tbody>
<tr>
{% for roi in rois %}
<td>${{roi}}</td>
{% endfor %}
</tr>
</tbody>
</table>
</div>
<!-- End of Tables -->
With Ajax I pass the data entered by the user over to python for processing:
<script>
function get_dates() {
const start_date = document.getElementById("start-date").value;
const end_date = document.getElementById("end-date").value;
$.ajax({
url: "/dashboard",
type: "POST",
data: {
start_date: start_date,
end_date: end_date,
},
});
}
</script>
Then in python:
#app.route("/dashboard", methods=["GET", "POST"])
#login_required
def dashboard():
default_roas_values, channels = get_default_roas_values(...)
default_start, default_end = get_default_start_end_times(...)
start_date = request.form.get("start_date")
end_date = request.form.get("end_date")
rois = [
calculate_roi(path, start_date, end_date)
for channel in channels
]
return render_template(
"dashboard.html",
channels=channels,
default_start=default_start,
default_end=default_end,
rois=rois
)
So far the data is retrieved and used for the calculation but the data is not updated on the frontend application. What could I be doing wrong or missing out? Please help

Django Toggle Div on Search Query

UPDATE
The solution is in the comments.
Original Post
I have a basic search query to find customers on one of my forms in my Django project. It returns results from the database in an HTML table. The query is executed by clicking the search button. I want to hide the div encapsulating the table when the query has not been executed.
Because the JS function is executed when the search button is clicked, the table only shows momentarily until the page reloads.
What is the convention for displaying a div after a query is executed, without having a constant toggle button?
views.py
#method_decorator(login_required, name='dispatch')
class CustomerResultsView(ListView):
model = CustomerName
template_name = 'parent/child.html'
context_object_name = 'filtered_customers'
#method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super().dispatch(*args, **kwargs)
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
context['form1'] = FilterForm(initial={
'name': self.request.GET.get('name', ''),
'filter_field': self.request.GET.get('filter_field', '')
})
context['users'] = self.request.user
context['form'] = Customer()
return context
def get_queryset(self):
query = self.request.GET.get('name')
filter_field = self.request.GET.get('filter_field')
if query:
return CustomerName.objects.filter(
Q(('%s__icontains' % filter_field, query))
)
else:
return {}
child.html
<form method="GET">
<legend class="border-bottom mb-4">Customer Lookup</legend>
<fieldset class="form-group">
{{ form1|crispy }}
</fieldset>
<div class="form-group">
<input type="submit" class="btn btn-outline-info mt-4" value="Search" onclick="showDiv()">
</div>
</form>
<hr>
<div class="table-responsive" id="custTabDiv" style="display:none">
<table id="testTable" class="table table-striped table-hover" cellspacing="0" width="100%">
<thead>
<tr>
<th class="th-sm" scope="col">First</th>
<th class="th-sm" scope="col">Last</th>
<th class="th-sm" scope="col">Phone</th>
</tr>
</thead>
<tbody>
<tr>
{% for name in filtered_customers %}
<tr>
<td id="test" onclick="customerNameValidation()">{{ name.first_name }}</td>
<td>{{ name.last_name }}</td>
<td>{{ name.phone }}</td>
</tr>
{% endfor %}
</tr>
</tbody>
</table>
<script>
function showDiv() {
document.getElementById("custTabDiv").style.display = "block";
}
</script>

How to pass checkbox values to modal bootstrap for Python Flask remove data from mysql table?

Environment:
Python 3.7.7
Flask 1.1.2
Werkzeug 1.0.1
Introduction:
I am making a Flask application for my saas dashboard.
I have a page "categories.html" which displays a list of categories in a table.
Each category has a checkbox if the user wants to delete several categories by checking the categories and clicking on the "DELETE" button. See screenshot below:
So users will be able to select multiple categories and remove them by clicking on the "DELETE" button.
But before to delete the rows in Mysql table categories, a confirmation popup is showing up. This popup is done by Bootstrap modal.
Problem:
I don't how to pass the list of checkbox values selected by the user to the modal popup.
What did I try:
I tried to fix this issue with some javascript code, but it doesn't work.
My code:
My template categories.html (I removed unecessary code):
<form>
<table id="categories" class="table dataTable no-footer" role="grid">
<thead>
<tr role="row">
<th tabindex="0" rowspan="1" colspan="1" style="white-space: nowrap"></th>
</tr>
</thead>
<tbody>
{% for category in categories %}
<tr role="row" >
<td style="white-space: nowrap">
<input name="category_id" value="{{ category.ID }}" type="checkbox" class="form-check-input" style="float: left; margin: 0 auto;">
</td>
<td>{{ category.name }}</td>
<td style="white-space: nowrap">
{% if category.icon %}
{% if category.icon.find('<i class')!=-1 %}
{{ category.icon|safe }}
{% else %}
<img src="{{ url_for('static', filename='images/<category.icon>') }}">
{% endif %}
{% else %}
na
{% endif %}
</td>
</tr>
{% endfor %}
</tr></tbody>
</table>
</form>
<!-- Modal -->
<div class="modal fade" id="deleteModal" tabindex="-1" role="dialog" aria-labelledby="deleteModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="deleteModalLabel">Delete Category</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
Are you sure you want to delete these categories?
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<form action="{{ url_for('delete_category')}}" method="POST">
<input name="category_id" type="hidden" value="pass_checkedvalue" id="hidden_checkedinput">
<input class="btn btn-danger" type="submit" value="delete"/>
</form>
</div>
</div>
</div>
</div>
<script>
$('#deleteModal').on('show.bs.modal', function(e) {
var checkedValues = $('.record:checked').map(function(){ return this.value; }).get();
//put the ids in the hidden input as a comma separated string
$('#hidden_checkedinput').val(checkedValues.join(','));
});
</script>
My route.py:
#app.route('/delete_category', methods=['GET', 'POST'])
#login_required
def delete_category():
if request.method == "POST":
if request.form["category_id"]:
print(request.form["category_id"])
Category.query.filter(Category.ID.in_(request.form["category_id"])).delete()
db_mysql.session.commit()
flash('The categories have been deleted', 'success')
return redirect(url_for('categories'))
My models.py:
class Category(db_mysql.Model):
__tablename__ = "W551je5v_pb_categories"
ID = db_mysql.Column('ID', db_mysql.Integer, primary_key=True)
name = db_mysql.Column('name', db_mysql.Unicode)
icon = db_mysql.Column('icon', db_mysql.Unicode)
icon_blue_img = db_mysql.Column('icon_blue_img', db_mysql.Unicode)
icon_white_img = db_mysql.Column('icon_white_img', db_mysql.Unicode)
icon_black_img = db_mysql.Column('icon_black_img', db_mysql.Unicode)
platforms = db_mysql.relationship('Platform', backref='W551je5v_pb_categories', lazy=True)
def __repr__(self):
return f"Category('{self.ID}','{self.name}','{self.icon}','{self.icon_blue_img}','{self.icon_white_img}','{self.icon_black_img}')"
OUTPUT:
When I execute this code, I get this error message:
sqlalchemy.exc.InvalidRequestError
sqlalchemy.exc.InvalidRequestError: Could not evaluate current criteria in Python: "Cannot evaluate clauselist with operator <function comma_op at 0x0000026EB4542558>". Specify 'fetch' or False for the synchronize_session parameter.
And the print(request.form["category_id"]) showed in console:
pass_checkedvalue
Which is the value of my hidden field.
I have no idea what am I doing wrong. Can anyone help me, please?
I don't how to pass the list of checkbox values selected by the user to the modal popup.
I don't think that's the right approach.
Actually, I don't think you need to pass ANY data to the modal popup.
What I would instead do is add an on-click for the modal button that would run a javascript function.That function needs to simply iterate over the <tr> tags and find the checked rows.
After you have a list containing the checked rows' IDs, you can send that to your backend via some HTTP request (you can use Javascript's FETCH API for that).
Your code would like something like that (please treat this as a schema since I don't actually know how your HTML looks like):
let checked_arr = [];
let tr_lst = document.getElementsByTagName('tr'); // probably better to be done with getElementsByClassName
for (let i=0; i<tr_lst.length; i++) {
let checkbox_td = tr_lst[i].children[0]; // assuming first <td> is the checkbox
let checkbox_element = checkbox_td.children[0]; // assuming your HTML looks like <td><input type="checkbox"...></td>
if (checkbox_element.checked) {
checked_arr.push(tr_lst[i].id);
}
}
let response = await fetch('/your_api_endpoint', {
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=utf-8'
},
body: JSON.stringify({"data": checked_arr})
});
Also, here is a nice tutorial on how to use FETCH API:
https://javascript.info/fetch
Hope that's helpful :)

Django the best way to create an edit modal form?

In one of my django app I have set the following architecture:
#models.py
class Income(models.Model):
price = models.DecimalField()
quantity = models.DecimalField()
date=models.DateField()
# forms.py
class IncomeForm(forms.ModelForm):
class Meta:
model = Income
fields = "__all__"
#views.py
def income_(request):
elements = Income.objects.all()
if request.method == 'POST':
form = IncomeForm(request.POST)
if form.is_valid():
new_input = form.save()
else :
form = IncomeForm()
elements = Income.objects.all()
context= {
'form': form,
'elements':elements,
}
return render(request, "income/income.html", context)
In my income.html file I have set the following
{% load crispy_forms_tags %}
<form id="" method="post">
<div class="form-group col-2 0 mb-0" >
{{form.quantity|as_crispy_field}}
</div>
<div class="form-group col-2 0 mb-0" >
{{form.price|as_crispy_field}}
</div>
<div class="form-group col-2 0 mb-0" >
{{form.date|as_crispy_field}}
</div>
</div>
After that I have created a table that list all data filled.
Now I want to create a button for each row that open a modal form that give me the possibility to modify the specific data for each id dataset.
I have tried to perform it with an ajax call, but I have had difficults to perform the form and the type of data (becouse in this manner I don't have the possibility to use crispy form or the forms model of the django framework).
So my question is: there is a simple way to achive my aim?
From what I understand from your question, you can try create a UpdateView in your view.py and redirect your html button with the object id to that view.
Updated answer-
since you are asking for simpler way implementing the edit page...
- models.py
class Income(models.Model):
price = models.DecimalField(decimal_places=2, max_digits=10000)
quantity = models.DecimalField(decimal_places=2, max_digits=10000)
date = models.DateField()
- urls.py
urlpatterns = [
path('income/', views.IncomeListView.as_view(), name='income'),
path('income_edit/<int:pk>', views.IncomeEdit.as_view(), name='income-edit'),
]
- views.py
class IncomeListView(ListView):
model = Income
template_name = 'income.html'
class IncomeEdit(UpdateView):
model = Income
form_class = IncomeForm
template_name = "income_form.html"
- forms.py
class IncomeForm(forms.ModelForm):
class Meta:
model = Income
fields = '__all__'
- income.html
<h1>Income List</h1>
<table>
<tr>
<th>ID</th>
<th>price</th>
<th>quantity</th>
<th>date</th>
</tr>
{% if income_list %}
{% for income in income_list %}
<tr>
<td>{{income.id}}</td>
<td>{{income.price}}</td>
<td>{{income.quantity}}</td>
<td>{{income.date}}</td>
<td>Edit </td>
</tr>
{% endfor %}
{% endif %}
</table>
- income_form.html
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit">
{{ form.media }}
</form>
please look into the class used for more information and understanding. hope this help =)

How can I get specific value from returned response

I'm trying to create shopping cart with laravel. I have a little problem to update cart items price onchange quantity number input. Ajax sends value and returns in array. But this time the problem is beginning.
This is my cart blade:
#extends('user.addons.app')
#push('customCss')
<link rel="stylesheet" href="
{{asset('/user/assets/css/numberinput.css')}}">
#endpush
#section('content')
#include('user.modules.header')
#include('user.modules.lsidebar')
<div id="cart-page-wrapper" class="pt-86 pt-md-56 pt-sm-46 pb-50 pb-md-20
pb-sm-10">
<div class="container">
<div class="row">
<div class="col-lg-8">
<div class="shopping-cart-list-area">
#include('user.modules.cart_data')
<div class="cart-coupon-update-area d-sm-flex justify-
content-between align-items-center">
<div class="coupon-form-wrap">
<form action="#" method="post">
<input type="text" placeholder="Coupon
Code"/>
<button class="btn-apply">Apply
Button</button>
</form>
</div>
<div class="cart-update-buttons mt-xs-14">
<button class="btn-clear-cart">Clear
Cart</button>
<button class="btn-update-cart">Update
Cart</button>
</div>
</div>
</div>
</div>
<div class="col-lg-4">
<!-- Cart Calculate Area -->
#include('user.modules.cartcalculate')
</div>
</div>
</div>
</div>
#include('user.modules.footer')
#endsection
#push('customJs')
#endpush
This is my cart_data blade:
<div class="shopping-cart-table table-responsive">
<table class="table table-bordered text-center" >
<thead>
<tr>
<th>Products</th>
<th>Price</th>
<th>Quantity</th>
<th>Total</th>
</tr>
</thead>
<tbody>
#foreach($carts as $cart)
<tr>
<td class="product-list">
<div class="cart-product-item d-flex align-items-center">
<div class="remove-icon">
<button><i class="fa fa-trash-o"></i></button>
</div>
<a href="single-product-sticky.html" class="product-
thumb">
<img src="{{asset($cart['image'])}}" alt="Product"/>
</a>
<a href="single-product-tab-left.html" class="product-
name">{{$cart['title']}}</a>
</div>
</td>
<td>
<span class="price">$ {{$cart['price']}}</span>
</td>
<td>
<input type="hidden" value="{{$cart['id']}}"
id="mon{{$cart['id']}}">
<div class="quantity">
<input type="number" min="1" max="9" step="1" value="
{{$cart['quantity']}}" id="qty{{$cart['id']}}">
</div>
</td>
<td>
<span class="price" id="toss{{$cart['id']}}">
{{$cart['price'] * $cart['quantity']}}
</span>
</td>
</tr>
#endforeach
</tbody>
</table>
</div>
<script src="{{asset('/assets/plugins/jquery/jquery.min.js')}}">
</script>
<script src="{{asset('/user/assets/js/numberinput.js')}}"></script>
<script>
#foreach($carts as $cart)
$("#qty{{$cart['id']}}").change(function(e){
e.preventDefault();
var value = $("#qty{{$cart['id']}}").val();
var id = $("#mon{{$cart['id']}}").val();
var inputQuantityElement = $("#x{{$cart['id']}}");
$.ajax({
type: 'post',
url: '/cartupdate',
data: {_token: '{{ csrf_token() }}',value:value, id:id},
success : function(response) {
$(inputQuantityElement).val(response);
}
});
});
#endforeach
</script>
And this is my function in controller:
public function cartupdate(Request $request)
{
$cartss = Cart::find($request['id']);
$quantity = $cartss->quantity;
if($quantity < $request['value'])
{
$update = $cartss->quantity+1;
}
else if($quantity > $request['value'])
{
$update = $cartss->quantity-1;
}
else
{
die;
}
$cartss->update(['quantity' => $update]);
$carts = Cart::where('user_id', Auth::user()->id)->get();
foreach ($carts as $cart)
{
$id[] = $cart['id'];
$pric[] = $cart['price'] * $cart['quantity'];
}
return $pric;
}
I want to change dynamicly prices when user clicked quantity input
In your cartupdate() function, return $pric won't give you the result because $pric is declared inside foreach(). Change it to:
$pric = 0;
foreach ($carts as $cart) {
$pric += $cart['price'] * $cart['quantity'];
}
return $pric;
will give you the total. But, I guess you are trying to get a new price for a particular cart. If so, change your cartupdate() function to:
public function cardupdate(Request $request) {
$cart = Cart::find($request['id']);
$quantity = $cart->quantity;
if($quantity < $request['value'])
{
$quantity++;
}
else if($quantity > $request['value']){
$quantity--;
}
$cart->update(['quantity' => $quantity]);
return $quantity*$cart->price;
}
To update the price in the view, you can use
document.getElementById("toss{{$cart['id']}}").innerHTML = response;
Personally, I suggest you to try Vue.js to build your application. Laravel + Vue.js is a good combination. It much easier to build complex application like this.
Sorry for my bad english :)

Categories

Resources