Django Stripe payment does not respond after clicking the Submit Payment button - python

I have an e-commerce application that I'm working on. The app is currently hosted on Heroku free account. At the moment I can select a product, add it on the cart and can get up to the stripe form and type in the card details, but when I click the 'Submit Payment' button nothing happens. I don't even get an error message. I'm using Stripe test keys and 4242 four times as my card number. Can anyone help me to find out what's going on pliz. I have been stuck on it for days.
Here is the relevant code below:
Settings.py code:
from .base import *
import dj_database_url
DEBUG = (os.environ.get('DEBUG_VALUE') == 'True')
ALLOWED_HOSTS = ['.herokuapp.com', '127.0.0.1']
AUTH_PASSWORD_VALIDATORS = [
{'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator'},
{'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator'},
{'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator'},
{'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator'}
]
""" DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': config('DB_NAME'),
'USER': config('DB_USER'),
'PASSWORD': config('DB_PASSWORD'),
'HOST': config('DB_HOST'),
'PORT': ''
}
}
"""
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
STRIPE_PUBLIC_KEY = os.environ.get('STRIPE_LIVE_PUBLIC_KEY')
STRIPE_SECRET_KEY = os.environ.get('STRIPE_LIVE_SECRET_KEY')
AWS_ACCESS_KEY_ID = os.environ.get('AWS_ACCESS_KEY_ID')
AWS_SECRET_ACCESS_KEY = os.environ.get('AWS_SECRET_ACCESS_KEY')
AWS_STORAGE_BUCKET_NAME = os.environ.get('AWS_STORAGE_BUCKET_NAME')
AWS_S3_FILE_OVERWRITE = False
AWS_DEFAULT_ACL = None
AWS_S3_REGION_NAME = "us-east-2"
AWS_S3_SIGNATURE_VERSION = "s3v4"
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = os.environ.get('EMAIL_USER')
EMAIL_HOST_PASSWORD = os.environ.get('EMAIL_PASSWORD')
# Heroku: Update database configuration from $DATABASE_URL.
db_from_env = dj_database_url.config(conn_max_age=500)
DATABASES['default'].update(db_from_env)
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.1/howto/static-files/
# The absolute path to the directory where collectstatic will collect static files for deployment.
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static_in_env')]
# The URL to use when referring to static files (where they will be served from)
STATIC_URL = '/static/'
# Simplified static file serving.
# https://warehouse.python.org/project/whitenoise/
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
views.py (Specifically the class PaymentView(View)):
from django.conf import settings
from django.contrib import messages
from django.core.exceptions import ObjectDoesNotExist
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.shortcuts import render, get_object_or_404
from django.views.generic import ListView, DetailView, View
from django.shortcuts import redirect
from django.utils import timezone
from django.db.models import Q
from .forms import CheckoutForm, CouponForm, RefundForm, PaymentForm
from .models import Item, OrderItem, Order, Address, Payment, Coupon, Refund, UserProfile
import random
import string
import stripe
stripe.api_key = settings.STRIPE_SECRET_KEY
class PaymentView(View):
def get(self, *args, **kwargs):
order = Order.objects.get(user=self.request.user, ordered=False)
if order.billing_address:
context = {
'order': order,
'DISPLAY_COUPON_FORM': False
}
userprofile = self.request.user.userprofile
if userprofile.one_click_purchasing:
# fetch the users card list
cards = stripe.Customer.list_sources(
userprofile.stripe_customer_id,
limit=3,
object='card'
)
card_list = cards['data']
if len(card_list) > 0:
# update the context with the default card
context.update({
'card': card_list[0]
})
return render(self.request, "payment.html", context)
else:
messages.warning(
self.request, "You have not added a billing address")
return redirect("core:checkout")
def post(self, *args, **kwargs):
order = Order.objects.get(user=self.request.user, ordered=False)
form = PaymentForm(self.request.POST)
print('form')
userprofile = UserProfile.objects.get(user=self.request.user)
if form.is_valid():
token = form.cleaned_data.get('stripeToken')
# print('token')
save = form.cleaned_data.get('save')
use_default = form.cleaned_data.get('use_default')
if save:
if userprofile.stripe_customer_id != '' and userprofile.stripe_customer_id is not None:
customer = stripe.Customer.retrieve(
userprofile.stripe_customer_id)
customer.sources.create(source=token)
else:
customer = stripe.Customer.create(
email=self.request.user.email,
)
customer.sources.create(source=token)
userprofile.stripe_customer_id = customer['id']
userprofile.one_click_purchasing = True
userprofile.save()
amount = order.get_total() * 100
try:
if use_default or save:
# charge the customer because we cannot charge the token more than once
charge = stripe.Charge.create(
amount=amount, # cents
currency="usd",
customer=userprofile.stripe_customer_id
)
else:
# charge once off on the token
charge = stripe.Charge.create(
amount=amount, # cents
currency="usd",
source=token
)
# create the payment
payment = Payment()
payment.stripe_charge_id = charge['id']
payment.user = self.request.user
payment.amount = order.get_total()
payment.save()
# assign the payment to the order
order_items = order.items.all()
order_items.update(ordered=True)
for item in order_items:
item.save()
order.ordered = True
order.payment = payment
order.ref_code = create_ref_code()
order.save()
messages.success(self.request, "Your order was successful!")
return redirect("/")
except stripe.error.CardError as e:
body = e.json_body
err = body.get('error', {})
messages.warning(self.request, f"{err.get('message')}")
return redirect("/")
except stripe.error.RateLimitError as e:
# Too many requests made to the API too quickly
print(e)
messages.warning(self.request, "Rate limit error")
return redirect("/")
except stripe.error.InvalidRequestError as e:
# Invalid parameters were supplied to Stripe's API
print(e)
messages.warning(self.request, "Invalid parameters")
return redirect("/")
except stripe.error.AuthenticationError as e:
# Authentication with Stripe's API failed
# (maybe you changed API keys recently)
print(e)
messages.warning(self.request, "Not authenticated")
return redirect("/")
except stripe.error.APIConnectionError as e:
# Network communication with Stripe failed
print(e)
messages.warning(self.request, "Network error")
return redirect("/")
except stripe.error.StripeError as e:
# Display a very generic error to the user, and maybe send
# yourself an email
print(e)
messages.warning(
self.request, "Something went wrong. You were not charged. Please try again.")
return redirect("/")
except Exception as e:
# send an email to ourselves
print(e)
messages.warning(
self.request, "A serious error occurred. We have been notifed.")
return redirect("/")
messages.warning(self.request, "Invalid data received")
return redirect("/payment/stripe/")
payment.html:
{% extends "base.html" %}
{% block extra_head %}
<style>
#stripeBtnLabel {
font-family: "Helvetica Neue", Helvetica, sans-serif;
font-size: 16px;
font-variant: normal;
padding: 0;
margin: 0;
-webkit-font-smoothing: antialiased;
font-weight: 500;
display: block;
}
#stripeBtn {
border: none;
border-radius: 4px;
outline: none;
text-decoration: none;
color: #fff;
background: #32325d;
white-space: nowrap;
display: inline-block;
height: 40px;
line-height: 40px;
box-shadow: 0 4px 6px rgba(50, 50, 93, .11), 0 1px 3px rgba(0, 0, 0, .08);
border-radius: 4px;
font-size: 15px;
font-weight: 600;
letter-spacing: 0.025em;
text-decoration: none;
-webkit-transition: all 150ms ease;
transition: all 150ms ease;
float: left;
width: 100%
}
button:hover {
transform: translateY(-1px);
box-shadow: 0 7px 14px rgba(50, 50, 93, .10), 0 3px 6px rgba(0, 0, 0, .08);
background-color: #43458b;
}
.stripe-form {
padding: 5px 30px;
}
#card-errors {
height: 20px;
padding: 4px 0;
color: #fa755a;
}
.stripe-form-row {
width: 100%;
float: left;
margin-top: 5px;
margin-bottom: 5px;
}
/**
* The CSS shown here will not be introduced in the Quickstart guide, but shows
* how you can use CSS to style your Element's container.
*/
.StripeElement {
box-sizing: border-box;
height: 40px;
padding: 10px 12px;
border: 1px solid transparent;
border-radius: 4px;
background-color: white;
box-shadow: 0 1px 3px 0 #e6ebf1;
-webkit-transition: box-shadow 150ms ease;
transition: box-shadow 150ms ease;
}
.StripeElement--focus {
box-shadow: 0 1px 3px 0 #cfd7df;
}
.StripeElement--invalid {
border-color: #fa755a;
}
.StripeElement--webkit-autofill {
background-color: #fefde5 !important;
}
.current-card-form {
display: none;
}
</style>
{% endblock extra_head %}
{% block content %}
<main>
<div class="container wow fadeIn">
<h2 class="my-5 h2 text-center">Payment</h2>
<div class="row">
<div class="col-md-12 mb-4">
<div class="card">
<script src="https://js.stripe.com/v3/"></script>
{% if card %}
<div style="padding: 5px 30px;">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" name="use_default_card" id="use_default_card">
<label class="custom-control-label" for="use_default_card">Use default card:
**** **** **** {{ card.last4 }}
<span>Exp: {{ card.exp_month }}/{{ card.exp_year }}</span></label>
</div>
</div>
{% endif %}
<div class="current-card-form">
<form action="." method="post" class="stripe-form">
{% csrf_token %}
<input type="hidden" name="use_default" value="true">
<div class="stripe-form-row">
<button id="stripeBtn">Submit Payment</button>
</div>
<div id="card-errors" role="alert"></div>
</form>
</div>
<div class="new-card-form">
<form action="." method="post" class="stripe-form" id="stripe-form">
{% csrf_token %}
<div class="stripe-form-row" id="creditCard">
<label for="card-element" id="stripeBtnLabel">
Credit or debit card
</label>
<div id="card-element" class="StripeElement StripeElement--empty">
<div class="__PrivateStripeElement"
style="margin: 0px !important; padding: 0px !important; border: none !important; display: block !important; background: transparent !important; position: relative !important; opacity: 1 !important;">
<iframe frameborder="0" allowtransparency="true" scrolling="no" name="__privateStripeFrame5"
allowpaymentrequest="true"
src="https://js.stripe.com/v3/elements-inner-card-19066928f2ed1ba3ffada645e45f5b50.html#style[base][color]=%2332325d&style[base][fontFamily]=%22Helvetica+Neue%22%2C+Helvetica%2C+sans-serif&style[base][fontSmoothing]=antialiased&style[base][fontSize]=16px&style[base][::placeholder][color]=%23aab7c4&style[invalid][color]=%23fa755a&style[invalid][iconColor]=%23fa755a&componentName=card&wait=false&rtl=false&keyMode=test&origin=https%3A%2F%2Fstripe.com&referrer=https%3A%2F%2Fstripe.com%2Fdocs%2Fstripe-js&controllerId=__privateStripeController1"
title="Secure payment input frame"
style="border: none !important; margin: 0px !important; padding: 0px !important; width: 1px !important; min-width: 100% !important; overflow: hidden !important; display: block !important; height: 19.2px;"></iframe><input
class="__PrivateStripeElement-input" aria-hidden="true" aria-label=" " autocomplete="false"
maxlength="1"
style="border: none !important; display: block !important; position: absolute !important; height: 1px !important; top: 0px !important; left: 0px !important; padding: 0px !important; margin: 0px !important; width: 100% !important; opacity: 0 !important; background: transparent !important; pointer-events: none !important; font-size: 16px !important;">
</div>
</div>
</div>
<div class="stripe-form-row">
<button id="stripeBtn">Submit Payment</button>
</div>
<div class="stripe-form-row">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" name="save" id="save_card_info">
<label class="custom-control-label" for="save_card_info">Save for future purchases
{{ STRIPE_PUBLIC_KEY }} {{ STRIPE_SECRET_KEY }}</label>
</div>
</div>
<div id="card-errors" role="alert"></div>
</form>
</div>
</div>
</div>
{% include "order_snippet.html" %}
</div>
</div>
</main>
{% endblock content %}
{% block extra_scripts %}
<script nonce=""> // Create a Stripe client.
var stripe = Stripe('STRIPE_PUBLIC_KEY');
// Create an instance of Elements.
var elements = stripe.elements();
// Custom styling can be passed to options when creating an Element.
// (Note that this demo uses a wider set of styles than the guide below.)
var style = {
base: {
color: '#32325d',
fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
fontSmoothing: 'antialiased',
fontSize: '16px',
'::placeholder': {
color: '#aab7c4'
}
},
invalid: {
color: '#fa755a',
iconColor: '#fa755a'
}
};
// Create an instance of the card Element.
var card = elements.create('card', { style: style });
// Add an instance of the card Element into the `card-element` <div>.
card.mount('#card-element');
// Handle real-time validation errors from the card Element.
card.addEventListener('change', function (event) {
var displayError = document.getElementById('card-errors');
if (event.error) {
displayError.textContent = event.error.message;
} else {
displayError.textContent = '';
}
});
// Handle form submission.
var form = document.getElementById('stripe-form');
form.addEventListener('submit', function (event) {
event.preventDefault();
stripe.createToken(card).then(function (result) {
if (result.error) {
// Inform the user if there was an error.
var errorElement = document.getElementById('card-errors');
errorElement.textContent = result.error.message;
} else {
// Send the token to your server.
stripeTokenHandler(result.token);
}
});
});
// Submit the form with the token ID.
function stripeTokenHandler(token) {
// Insert the token ID into the form so it gets submitted to the server
var form = document.getElementById('stripe-form');
var hiddenInput = document.createElement('input');
hiddenInput.setAttribute('type', 'hidden');
hiddenInput.setAttribute('name', 'stripeToken');
hiddenInput.setAttribute('value', token.id);
form.appendChild(hiddenInput);
// Submit the form
form.submit();
}
var currentCardForm = $('.current-card-form');
var newCardForm = $('.new-card-form');
var use_default_card = document.querySelector("input[name=use_default_card]");
use_default_card.addEventListener('change', function () {
if (this.checked) {
newCardForm.hide();
currentCardForm.show()
} else {
newCardForm.show();
currentCardForm.hide()
}
})
</script>
{% endblock extra_scripts %}

You should pass the API key along with other variables in the context variable by adding:
'STRIPE_PUBLIC_KEY': settings.STRIPE_PUBLIC_KEY,
inside the context variable.

Related

Django Stripe Payment Responds with Invalid Parameter after clicking Submit Payment button

I am working on an e-commerce project that requires stripe payment gateway. It is my first time to work on an application that requires stripe payment. I am a junior programmer. I am working on my localhost machine, I have tried to debug the code but i have failed to see where the problem is. #Hacker86 got the solution but has not shared it can anyone help me with the problem.
This is the link of the same problem Stack
I tried to solve the problem with the solution in the replies to above the question but all was in veil. So please can anyone help immediately reply me.
Below is my relevant Code
base.py
import os
from decouple import config
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = os.path.dirname(os.path.dirname(
os.path.dirname(os.path.abspath(__file__))))
SECRET_KEY = config('SECRET_KEY')
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.sites',
'allauth',
'allauth.account',
'allauth.socialaccount',
'rest_framework',
'drf_yasg',
'crispy_forms',
'django_countries',
'core',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'perfectfits.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'perfectfits.wsgi.application'
# Internationalization
# https://docs.djangoproject.com/en/3.1/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.1/howto/static-files/
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static_in_env')]
STATIC_ROOT = os.path.join(BASE_DIR, 'static_root')
MEDIA_ROOT = os.path.join(BASE_DIR, 'media_root')
# Auth
AUTHENTICATION_BACKENDS = (
# Needed to login by username in Django admin, regardless of `allauth`
'django.contrib.auth.backends.ModelBackend',
# `allauth` specific authentication methods, such as login by e-mail
'allauth.account.auth_backends.AuthenticationBackend',
)
SITE_ID = 1
LOGIN_REDIRECT_URL = '/'
# CRISPY FORMS
CRISPY_TEMPLATE_PACK = 'bootstrap4'
views.py
from django.conf import settings
from django.contrib import messages
from django.core.exceptions import ObjectDoesNotExist
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import request
from django.shortcuts import render, redirect, get_object_or_404
from django.views.generic import ListView, DetailView, View
from django.utils import timezone
from .forms import CheckoutForm, CouponForm, RefundForm
from .models import Item, OrderItem, Order, BillingAddress, Payment, Coupon, Refund
import random
import string
import stripe
stripe.api_key = settings.STRIPE_SECRET_KEY
def create_ref_code():
return ''.join(random.choices(string.ascii_lowercase + string.digits, k=20))
# Create your views here.
def products(request):
context = {
'items': Item.objects.all()
}
return render(request, "products.html")
class CheckoutView(View):
def get(self, *args, **kwargs):
try:
order = Order.objects.get(user=self.request.user, ordered=False)
form = CheckoutForm()
context = {
'form': form,
'couponform': CouponForm(),
'order': order,
'DISPLAY_COUPON_FORM': True
}
return render(self.request, "checkout.html", context)
except ObjectDoesNotExist:
messages.info(self.request, "You do not have an active order")
return redirect("core:checkout")
def post(self, *args, **kwargs):
form = CheckoutForm(self.request.POST or None)
try:
order = Order.objects.get(user=self.request.user, ordered=False)
if form.is_valid():
street_address = form.cleaned_data.get('street_address')
apartment_address = form.cleaned_data.get('apartment_address')
country = form.cleaned_data.get('country')
zip = form.cleaned_data.get('zip')
# TODO: add functionality for these fields
# same_shipping_address = form.cleaned_data.get('same_shipping_address')
# save_info = form.cleaned_data.get('save_info')
payment_option = form.cleaned_data.get('payment_option')
billing_address = BillingAddress(
user=self.request.user,
street_address=street_address,
apartment_address=apartment_address,
country=country,
zip=zip
)
billing_address.save()
order.billing_address = billing_address
order.save()
if payment_option == 'S':
return redirect('core:payment', payment_option='stripe')
elif payment_option =='P':
return redirect('core:payment', payment_option='paypal')
elif payment_option =='M':
return redirect('core:payment', payment_option='mobilemoney')
else:
messages.warning(self.request, "Invalid payment option selected")
return redirect('core:checkout')
except ObjectDoesNotExist:
messages.warning(self.request, "You do not have an active order")
return redirect("core:order-summary")
class PaymentView(View):
def get(self, *args, **kwargs):
# order
order = Order.objects.get(user=self.request.user, ordered=False)
if order.billing_address:
context = {
'order': order,
'DISPLAY_COUPON_FORM': False,
'STRIPE_PUBLIC_KEY' : settings.STRIPE_PUBLIC_KEY,
}
return render(self.request, "payment.html", context)
else:
messages.warning(
self.request, "You have not added a billing address")
return redirect("core:checkout")
def post(self, *args, **kwargs):
order = Order.objects.get(user=self.request.user, ordered=False)
token = self.request.POST.get('stripeToken')
amount = order.get_total()
try:
charge = stripe.Charge.create(
amount=amount, # cents
currency="ugx",
source=token
)
# create the payment
payment = Payment()
payment.stripe_charge_id = charge['id']
payment.user = self.request.user
payment.amount = order.get_total()
payment.save()
# Assign the payment to the order
order_items = order.items.all()
order_items.update(ordered=True)
for item in order_items:
item.save()
order.ordered = True
order.payment = payment
order.ref_code = create_ref_code()
order.save()
messages.success(self.request, "Your order was successful!")
return redirect("/")
except stripe.error.CardError as e:
body = e.json_body
err = body.get('error', {})
messages.warning(self.request, f"{err.get('message')}")
return redirect("/")
except stripe.error.RateLimitError as e:
# Too many requests made to the API too quickly
messages.warning(self.request,"Rate limit error")
return redirect("/")
except stripe.error.InvalidRequestError as e:
# Invalid parameters were supplied to Stripe's API
messages.warning(self.request, "Invalid parameters")
return redirect("/")
except stripe.error.AuthenticationError as e:
# Authentication with Stripe's API failed
# (maybe you changed API keys recently)
messages.warning(self.request, "Not authenticated")
return redirect("/")
except stripe.error.APIConnectionError as e:
# Network communication with Stripe failed
messages.warning(self.request, "Network error")
return redirect("/")
except stripe.error.StripeError as e:
# Display a very generic error to the user, and maybe send
# yourself an email
messages.warning(self.request, "Something went wrong. You were not charged. Please try again")
return redirect("/")
except Exception as e:
# Send an email to ourselves
messages.warning(self.request, "A serious error occurred. We have been notified")
return redirect("/")
class HomeView(ListView):
model = Item
paginate_by = 10
template_name = "home.html"
class OrderSummaryView(LoginRequiredMixin, View):
def get(self, *args, **kwargs):
try:
order = Order.objects.get(user=self.request.user, ordered=False)
context = {
'object': order
}
return render(self.request, 'order_summary.html', context)
except ObjectDoesNotExist:
messages.warning(self.request, "You do not have an active order")
return redirect("/")
class ItemDetailView(DetailView):
model = Item
template_name = "product.html"
#login_required
def add_to_cart(request, slug):
item = get_object_or_404(Item, slug=slug)
order_item, created = OrderItem.objects.get_or_create(
item=item,
user=request.user,
ordered=False
)
order_qs = Order.objects.filter(user=request.user, ordered=False) # qs is query set
if order_qs.exists():
order = order_qs[0]
# check if the order item is in the order
if order.items.filter(item__slug=item.slug).exists():
order_item.quantity += 1
order_item.save()
messages.info(request, "This item quantity was updated.")
return redirect("core:order-summary")
else:
order.items.add(order_item)
messages.info(request, "This item was added to your Cart.")
return redirect("core:order-summary")
else:
ordered_date = timezone.now()
order = Order.objects.create(
user=request.user, ordered_date=ordered_date)
order.items.add(order_item)
messages.info(request, "This item was added to your Cart.")
return redirect("core:order-summary")
#login_required
def remove_from_cart(request, slug):
item = get_object_or_404(Item, slug=slug)
order_qs = Order.objects.filter(
user=request.user,
ordered=False
)
if order_qs.exists():
order = order_qs[0]
# check if the order item is in the order
if order.items.filter(item__slug=item.slug).exists():
order_item = OrderItem.objects.get_or_create(
item=item,
user=request.user,
ordered=False
)[0]
order.items.remove(order_item)
messages.info(request, "This item was removed from your Cart.")
return redirect("core:order-summary")
else:
messages.info(request, "This item was not in your cart.")
return redirect("core:product", slug=slug)
else:
messages.info(request, "You do not have an active order.")
return redirect("core:product", slug=slug)
#login_required
def remove_single_item_from_cart(request, slug):
item = get_object_or_404(Item, slug=slug)
order_qs = Order.objects.filter(
user=request.user,
ordered=False
)
if order_qs.exists():
order = order_qs[0]
# check if the order item is in the order
if order.items.filter(item__slug=item.slug).exists():
order_item = OrderItem.objects.get_or_create(
item=item,
user=request.user,
ordered=False
)[0]
if order_item.quantity > 1:
order_item.quantity -= 1
order_item.save()
else:
order.items.remove(order_item)
messages.info(request, "This item quantity was updated.")
return redirect("core:order-summary")
else:
messages.info(request, "This item was not in your cart.")
return redirect("core:product", slug=slug)
else:
messages.info(request, "You do not have an active order.")
return redirect("core:product", slug=slug)
def get_coupon(request, code):
try:
coupon = Coupon.objects.get(code=code)
return coupon
except ObjectDoesNotExist:
messages.info(request, "This Coupon does not exist")
return redirect("core:checkout")
class AddCouponView(View):
def post(self, *args, **kwargs):
form = CouponForm(self.request.POST or None)
if form.is_valid():
try:
code = form.cleaned_data.get('code')
order = Order.objects.get(
user=self.request.user, ordered=False)
order.coupon = get_coupon(self.request, code)
order.save()
messages.success(self.request, "Successfully added coupon")
return redirect("core:checkout")
except ObjectDoesNotExist:
messages.info(self.request, "You do not have an active order")
return redirect("core:checkout")
class RequestRefundView(View):
def get(self, *args, **kwargs):
form = RefundForm()
context = {
'form': form
}
return render(self.request, "request_refund.html", context)
def post(self, *args, **kwargs):
form = RefundForm(self.request.POST)
if form.is_valid():
ref_code = form.cleaned_data.get('ref_code')
message = form.cleaned_data.get('message')
email = form.cleaned_data.get('email')
# edit the order
try:
order = Order.objects.get(ref_code=ref_code)
order.refund_requested = True
order.save()
# store the refund
refund = Refund()
refund.order = order
refund.reason = message
refund.email = email
refund.save()
messages.info(self.request, "Your request was received.")
return redirect("core:request-refund")
except ObjectDoesNotExist:
messages.info(self.request, "This order does not exist.")
return redirect("core:request-refund")
payment.html
{% extends "base.html" %}
{% block extra_head %}
<style>
#stripeBtnLabel {
font-family: "Helvetica Neue", Helvetica, sans-serif;
font-size: 16px;
font-variant: normal;
padding: 0;
margin: 0;
-webkit-font-smoothing: antialiased;
font-weight: 500;
display: block;
}
#stripeBtn {
border: none;
border-radius: 4px;
outline: none;
text-decoration: none;
color: #fff;
background: #32325d;
white-space: nowrap;
display: inline-block;
height: 40px;
line-height: 40px;
box-shadow: 0 4px 6px rgba(50, 50, 93, .11), 0 1px 3px rgba(0, 0, 0, .08);
border-radius: 4px;
font-size: 15px;
font-weight: 600;
letter-spacing: 0.025em;
text-decoration: none;
-webkit-transition: all 150ms ease;
transition: all 150ms ease;
float: left;
width: 100%
}
button:hover {
transform: translateY(-1px);
box-shadow: 0 7px 14px rgba(50, 50, 93, .10), 0 3px 6px rgba(0, 0, 0, .08);
background-color: #43458b;
}
.stripe-form {
padding: 5px 30px;
}
#card-errors {
height: 20px;
padding: 4px 0;
color: #fa755a;
}
.stripe-form-row {
width: 100%;
float: left;
margin-top: 5px;
margin-bottom: 5px;
}
/**
* The CSS shown here will not be introduced in the Quickstart guide, but shows
* how you can use CSS to style your Element's container.
*/
.StripeElement {
box-sizing: border-box;
height: 40px;
padding: 10px 12px;
border: 1px solid transparent;
border-radius: 4px;
background-color: white;
box-shadow: 0 1px 3px 0 #e6ebf1;
-webkit-transition: box-shadow 150ms ease;
transition: box-shadow 150ms ease;
}
.StripeElement--focus {
box-shadow: 0 1px 3px 0 #cfd7df;
}
.StripeElement--invalid {
border-color: #fa755a;
}
.StripeElement--webkit-autofill {
background-color: #fefde5 !important;
}
.current-card-form {
display: none;
}
</style>
{% endblock extra_head %}
{% block content %}
<main >
<div class="container wow fadeIn">
<h2 class="my-5 h2 text-center">Payment</h2>
<div class="row">
<div class="col-md-12 mb-4">
<div class="card">
{% if card %}
<div style="padding: 5px 30px;">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" name="use_default_card" id="use_default_card">
<label class="custom-control-label" for="use_default_card">Use default card:
**** **** **** {{ card.last4 }}
<span>Exp: {{ card.exp_month }}/{{ card.exp_year }}</span></label>
</div>
</div>
{% endif %}
<div class="current-card-form">
<form action="." method="post" class="stripe-form">
{% csrf_token %}
<input type="hidden" name="use_default" value="true">
<div class="stripe-form-row">
<button id="stripeBtn">Submit Payment</button>
</div>
<div id="card-errors" role="alert"></div>
</form>
</div>
<div class="new-card-form">
<form action="." method="post" class="stripe-form" id="stripe-form">
{% csrf_token %}
<div class="stripe-form-row" id="creditCard">
<label for="card-element" id="stripeBtnLabel">
Credit or debit card
</label>
<div id="card-element" class="StripeElement StripeElement--empty"><div class="__PrivateStripeElement" style="margin: 0px !important; padding: 0px !important; border: none !important; display: block !important; background: transparent !important; position: relative !important; opacity: 1 !important;"><iframe frameborder="0" allowtransparency="true" scrolling="no" name="__privateStripeFrame5" allowpaymentrequest="true" src="https://js.stripe.com/v3/elements-inner-card-19066928f2ed1ba3ffada645e45f5b50.html#style[base][color]=%2332325d&style[base][fontFamily]=%22Helvetica+Neue%22%2C+Helvetica%2C+sans-serif&style[base][fontSmoothing]=antialiased&style[base][fontSize]=16px&style[base][::placeholder][color]=%23aab7c4&style[invalid][color]=%23fa755a&style[invalid][iconColor]=%23fa755a&componentName=card&wait=false&rtl=false&keyMode=test&origin=https%3A%2F%2Fstripe.com&referrer=https%3A%2F%2Fstripe.com%2Fdocs%2Fstripe-js&controllerId=__privateStripeController1" title="Secure payment input frame" style="border: none !important; margin: 0px !important; padding: 0px !important; width: 1px !important; min-width: 100% !important; overflow: hidden !important; display: block !important; height: 19.2px;"></iframe><input class="__PrivateStripeElement-input" aria-hidden="true" aria-label=" " autocomplete="false" maxlength="1" style="border: none !important; display: block !important; position: absolute !important; height: 1px !important; top: 0px !important; left: 0px !important; padding: 0px !important; margin: 0px !important; width: 100% !important; opacity: 0 !important; background: transparent !important; pointer-events: none !important; font-size: 16px !important;"></div></div>
</div>
<div class="stripe-form-row">
<button id="stripeBtn">Submit Payment</button>
</div>
<div class="stripe-form-row">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" name="save" id="save_card_info">
<label class="custom-control-label" for="save_card_info">Save for future purchases</label>
</div>
</div>
<div id="card-errors" role="alert"></div>
</form>
</div>
</div>
</div>
{% include "order_snippet.html" %}
</div>
</div>
</main>
{% endblock content %}
{% block extra_scripts %}
<script src="https://js.stripe.com/v3/"></script>
<script nonce=""> // Create a Stripe client.
var stripe = Stripe('{{STRIPE_PUBLIC_KEY}}');
// Create an instance of Elements.
var elements = stripe.elements();
// Custom styling can be passed to options when creating an Element.
// (Note that this demo uses a wider set of styles than the guide below.)
var style = {
base: {
color: '#32325d',
fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
fontSmoothing: 'antialiased',
fontSize: '16px',
'::placeholder': {
color: '#aab7c4'
}
},
invalid: {
color: '#fa755a',
iconColor: '#fa755a'
}
};
// Create an instance of the card Element.
var card = elements.create('card', {style: style});
// Add an instance of the card Element into the `card-element` <div>.
card.mount('#card-element');
// Handle real-time validation errors from the card Element.
card.addEventListener('change', function(event) {
var displayError = document.getElementById('card-errors');
if (event.error) {
displayError.textContent = event.error.message;
} else {
displayError.textContent = '';
}
});
// Handle form submission.
var form = document.getElementById('stripe-form');
form.addEventListener('submit', function(event) {
event.preventDefault();
stripe.createToken(card).then(function(result) {
if (result.error) {
// Inform the user if there was an error.
var errorElement = document.getElementById('card-errors');
errorElement.textContent = result.error.message;
} else {
// Send the token to your server.
stripeTokenHandler(result.token);
}
});
});
// Submit the form with the token ID.
function stripeTokenHandler(token) {
// Insert the token ID into the form so it gets submitted to the server
var form = document.getElementById('stripe-form');
var hiddenInput = document.createElement('input');
hiddenInput.setAttribute('type', 'hidden');
hiddenInput.setAttribute('name', 'stripeToken');
hiddenInput.setAttribute('value', token.id);
form.appendChild(hiddenInput);
// Submit the form
form.submit();
}
var currentCardForm = $('.current-card-form');
var newCardForm = $('.new-card-form');
var use_default_card = document.querySelector("input[name=use_default_card]");
use_default_card.addEventListener('change', function() {
if (this.checked) {
newCardForm.hide();
currentCardForm.show()
} else {
newCardForm.show();
currentCardForm.hide()
}
})
</script>
{% endblock extra_scripts %}

jinja2.exceptions.UndefinedError is undefined

I had a problem with this jinja2.exception and I was totally confused why. I wanted to post data to my .html, which I got from an API.
#app.route("/playerstats", methods = ["GET"])
def statsget():
return render_template("stats.html")
#app.route("/playerstats", methods = ["POST"])
def statspost():
player_uri = "https://www.balldontlie.io/api/v1/players?search={}%20{}"
playerinput = request.form["nm"]
player_split = playerinput.split()
vn = player_split[0]
nn = player_split[1]
r = requests.get(player_uri.format(vn, nn)).json()
data = {
"player_id": r["data"][0]["id"],
"player_first_name": r["data"][0]["first_name"]
}
return render_template("stats.html", data=data)
<button type="button" class="btn btn-outline-secondary" style="height: 40px; width: 450px; margin-top: 5px; margin-bottom: 5px; border-width: 1px; border-color:lightgrey; text-align: start;">
{{data.player_first_name}} {{data.player_id}}
</button>
Running the webpage put out this exception: jinja2.exceptions.UndefinedError 'data' is undefined
My solution was to put the data I get from the api into an array and run a for-loop inside the html to give out all data:
inside main.py:
#app.route("/playerstats", methods = ["GET"])
def pstatsget():
return render_template("stats.html")
#app.route("/playerstats", methods = ["POST"])
def pstatspost():
player_uri = "https://www.balldontlie.io/api/v1/players?search={}%20{}"
playerinput = request.form["nm"]
player_split = playerinput.split()
vn = player_split[0]
nn = player_split[1]
r = requests.get(player_uri.format(vn, nn)).json()
data_group = []
data = {
"player_id": r["data"][0]["id"],
"player_first_name": r["data"][0]["first_name"]
}
data_group.append(data)
print(data_group)
return render_template("stats.html", data=data_group)
inside stats.html:
{% for d in data: %}
<button type="button" class="btn btn-outline-secondary" style="height: 40px; width: 450px; margin-top: 5px; margin-bottom: 5px; border-width: 1px; border-color:lightgrey; text-align: start;">
{{d.player_first_name}} {{d.player_id}}
</button>
{% endfor %}
I hope this works for you aswell!

Plotly.offline plot output_type='div' not working inside HTML - How to embed Plotly to HTML

I have created a simple Flask app which renders a template 'index.html' and in that HTML I am attempting to list various plots as a sort of dashboard-style webpage with other content. I know the basics of Flask and Dash though am not using Dash as I want to have more control over the HTML/CSS hence using Flask to create a website to embed the graphs using Plotly.
So far I've had no luck with any of the official documentation or any medium.com or suchlike articles. The closest I have come to is this answer: Embedding dash plotly graphs into html
However, it isn't working when I run my app and the browser launches in localhost. Instead it just gives me a lot of text which is clearly the plotly figure, but it isn't turning into a graph.
Here is all my py/html/css even if the navbar stuff isn't relevant; just in case (I am still learning so I'm sure there will be some better ways to do things..)
Thanks for any help.
DataFrame class which grabs the latest Coronavirus data and returns as pandas.dataframe:
import pandas as pd
import requests
class DataFrame:
"""
Class which grabs the data live from the ECDC and returns it in a pandas dataframe
"""
def __init__(self):
"""
Creating the pandas dataframe of the ECDC JSON data
"""
self.url = "https://opendata.ecdc.europa.eu/covid19/casedistribution/json"
self.file = requests.get(self.url).json()
self.file = self.file['records']
self.df = pd.DataFrame(data=self.file)
def converter(self):
"""
Converting the dtypes from object to int for ints, and date to date
Also renames the columns to more visual-friendly names
:return: None
"""
self.df['cases'] = self.df['cases'].astype(int)
self.df['deaths'] = self.df['deaths'].astype(int)
self.df['popData2018'] = self.df['popData2018'].astype(str).replace('', 0).astype(int)
self.df['dateRep'] = self.df['dateRep'].to_timestamp
cols_rename = 'date day month year cases deaths country geo_id country_id population continent'.split()
cols_rename = [s.capitalize() for s in cols_rename]
self.df.columns = cols_rename
def return_df(self):
"""
:return: pandas DataFrame
"""
self.converter()
return self.df
app.py
from plotly.offline import plot
import plotly.graph_objects as go
from dataframe.dataframe import DataFrame
from flask import Flask, render_template, redirect, request, url_for
app = Flask(__name__)
def graph_maker():
df = DataFrame().return_df()
data = []
for continent in df['Continent'].unique():
df_filt = df[df['Continent'] == continent]
data.append(go.Scatter(x=df_filt["Cases"],
y=df_filt["Deaths"],
mode='markers',
text=df_filt['Country'],
name=continent))
layout = go.Layout(title="Deaths (Y) v Cases (X) by continent")
fig = go.Figure(data=data, layout=layout)
return plot(figure_or_data=fig,
include_plotlyjs=False,
output_type='div')
#app.route('/')
def index():
graph = graph_maker()
return render_template('index.html',
graph=graph)
if __name__ == '__main__':
app.run(debug=True)
index.html
{% extends "navbar.html" %}
<head>
<meta charset="UTF-8">
<link type="text/css" rel="stylesheet" href="..\static\master.css">
<link href="https://fonts.googleapis.com/css2?family=Maven+Pro&display=swap" rel="stylesheet">
<!-- Plotly.js -->
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
</head>
{% block nbar %}
<body>
<div class="global-box" id="global-stats">
<h1>Global charts</h1>
<p>Title here</p>
<ul class="global-box-ul">
<li class="global-box-ul-li">
{{ graph }}
</li>
<li class="global-box-ul-li">
Another chart here
</li>
</ul>
</div>
</body>
{% endblock %}
navbar.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>C19DB</title>
<meta charset="UTF-8">
<link type="text/css" rel="stylesheet" href="..\static\master.css">
<link href="https://fonts.googleapis.com/css2?family=Maven+Pro&display=swap" rel="stylesheet">
</head>
<nav class="navbar">
<div class="logo">c19db</div>
<div class="list">
<ul class="navbar_items">
<li class="navbar_item">Dashboard</li>
<li class="navbar_item">About</li>
<li class="navbar_item">Register</li>
</ul>
</div>
</nav>
{% block nbar %}
{% endblock %}
</html>
master.css
html, body {
font-family: 'Maven Pro';
height: 700px;
margin: 0;
}
.navbar {
background: rgb(237, 232, 232);
vertical-align: middle;
}
.logo {
vertical-align: middle;
display: inline-block;
color: rgb(196, 69, 69);
font-size: 50px;
width: 250px;
padding: 5px 15px 5px 15px;
}
.list{
vertical-align: middle;
display: inline-block;
width: calc(100% - 285px);
text-align: right;
}
.navbar_items {
list-style: none;
font-size: 20px;
color: rgb(61, 61, 61)
}
.navbar_item{
display: inline-block;
padding: 5px 15px 5px 15px;
}
a {
text-decoration: none;
}
.navbar_item > a{
display: inline-block;
padding: 5px 15px 5px 15px;
color: rgb(61, 61, 61);
}
.navbar_item > a:hover {
display: inline-block;
padding: 5px 15px 5px 15px;
color: rgb(196, 69, 69);
}
.footer, .footer a {
position: relative;
background: rgb(237, 232, 232, 0.2);
width: 100%;
color: rgb(61, 61, 61, 0.2);
text-align: center;
}
span {
font-weight: bold;
}
.global-box {
text-align: center;
border: 2px black solid;
list-style: none;
margin: auto;
}
.global-box > h1, .global-box > p {
margin: 1px;
}
ul {
display: contents;
}
.global-box-ul-li {
display: inline-block;
border: 2px lightblue solid;
list-style: none;
margin: auto;
width: 48%;
height: 100%;
}
Thank you for any help!
I have solved this problem.
Nutshell:
Create a chart
Call pyo.plot() as normal passing through the fig, output_type='div' and include_plotlyjs=False
Have that output to a variable passed through Markup() (import from flask)
Have the Markup(variable) passed through the render_template like you would a form
Have the variable rendered in the html using {{ jinja template }}
First, create your Plotly chart like normal. I will not give a whole example but just the key points. I create charts in functions for import and use in multiple pages if necessary. In this case, it's necessary because the chart must be assigned to a variable.
def my_bar_chart():
*snip irrelevant*
my_bar_chart = pyo.plot(fig, output_type='div', include_plotlyjs=False)
return Markup(my_bar_chart)
Now import your function to your app.py / wherever your views are and pass it through render template as you would any form, for example.
Here is an example:
def my_page():
my_bar_chart_var = my_bar_chart()
return render_template('my_page.html',
bar_chart_1=my_bar_chart_var)
Then on the html for that page simply pass through bar_chart_1 in a jinja template like so:
{{ bar_chart_1 }}
And done.

I'm trying to use stripe payment. But having some issues on submitting card details

Im following just django tutorial. I'm unable to get any success message or error message after clicking submit button. the page is not even getting redirected after clicking submit button. dont know where i went wrong with my post method. P.s. Ive created my stripe acc and Ive used those public and private keys. Any help is appreciated. TIA
payment.html
{% extends 'base.html' %}
{% block content %}
<main class="mt-5 pt-4">
<div class="container wow fadeIn">
<h2 class="my-5 h2 text-center">Payment</h2>
<div class="row">
<div class="col-md-12 mb-4">
<div class="card">
<script src="https://js.stripe.com/v3/"></script>
<form action="." method="post" id="stripe-form">
{% csrf_token %}
<div class="stripe-form-row">
<label for="card-element" id="stripeBtnLabel">
Credit or debit card
</label>
<div id="card-element" class="StripeElement StripeElement--empty"><div class="__PrivateStripeElement" style="margin: 0px !important; padding: 0px !important; border: medium none !important; display: block !important; background: transparent none repeat scroll 0% 0% !important; position: relative !important; opacity: 1 !important;"><iframe allowtransparency="true" scrolling="no" name="__privateStripeFrame5" allowpaymentrequest="true" src="https://js.stripe.com/v3/elements-inner-card-fbfeb5b62d598125b16ab6addef894d6.html#style[base][color]=%2332325d&style[base][fontFamily]=%22Helvetica+Neue%22%2C+Helvetica%2C+sans-serif&style[base][fontSmoothing]=antialiased&style[base][fontSize]=16px&style[base][::placeholder][color]=%23aab7c4&style[invalid][color]=%23fa755a&style[invalid][iconColor]=%23fa755a&componentName=card&wait=false&rtl=false&keyMode=test&apiKey=pk_test_i0vc3rYRd3tcPmIsJIIQOiiI00khWr20iQ&origin=https%3A%2F%2Fstripe.com&referrer=https%3A%2F%2Fstripe.com%2Fdocs%2Fstripe-js&controllerId=__privateStripeController1" title="Secure payment input frame" style="border: medium none !important; margin: 0px !important; padding: 0px !important; width: 1px !important; min-width: 100% !important; overflow: hidden !important; display: block !important; height: 19.2px;" frameborder="0"></iframe><input class="__PrivateStripeElement-input" aria-hidden="true" aria-label=" " autocomplete="false" maxlength="1" style="border: medium none !important; display: block !important; position: absolute !important; height: 1px !important; top: 0px !important; left: 0px !important; padding: 0px !important; margin: 0px !important; width: 100% !important; opacity: 0 !important; background: transparent none repeat scroll 0% 0% !important; pointer-events: none !important; font-size: 16px !important;"></div></div>
<!-- Used to display form errors. -->
<div id="card-errors" role="alert"></div>
</div>
<button id="stripeBtn">Submit Payment</button>
</form>
</div>
<!--/.Card-->
</div>
<!--Grid column-->
</div>
<!--Grid row-->
</div>
</main>
{% endblock content %}
{% block extra_scripts %}
<script type="text/javascript" nonce="zQL2oP9DrQhQ+sjXkd3Usg=="> // Create a Stripe client.
var stripe = Stripe('acc key');
var elements = stripe.elements();
var card = elements.create('card', {style: style});
card.mount('#card-element');
card.addEventListener('change', function(event) {
var displayError = document.getElementById('card-errors');
if (event.error) {
displayError.textContent = event.error.message;
} else {
displayError.textContent = '';
}
});
var form = document.getElementById('stripe-form');
form.addEventListener('submit', function(event) {
event.preventDefault();
stripe.createToken(card).then(function(result) {
if (result.error) {
var errorElement = document.getElementById('card-errors');
errorElement.textContent = result.error.message;
} else {
stripeTokenHandler(result.token);
}
});
});
function stripeTokenHandler(token) {
// Insert the token ID into the form so it gets submitted to the server
var form = document.getElementById('stripe-form');
var hiddenInput = document.createElement('input');
hiddenInput.setAttribute('type', 'hidden');
hiddenInput.setAttribute('name', 'stripeToken');
hiddenInput.setAttribute('value', token.id);
form.appendChild(hiddenInput);
// Submit the form
form.submit();
}
var successElement = document.getElementById('stripe-token-handler');
document.querySelector('.wrapper').addEventListener('click', function() {
successElement.className = 'is-hidden';
});
function stripeTokenHandler(token) {
successElement.className = '';
successElement.querySelector('.token').textContent = token.id;
}
</script>
{% endblock extra_scripts %}
views.py
class PaymentView(View):
def get(self, *args, **kwargs):
print("get mothod")
return render(self.request, "payment.html")
def post(self, *args, **kwargs):
print("post method")
order = Order.objects.get(user=self.request.user, ordered=False)
token = self.request.POST.get('stripeToken')
amount=order.get_total_price()
print(self.user.POST)
try:
print("try loop")
# Use Stripe's library to make requests...
charge = stripe.Charge.create(
amount=amount,
currency="inr",
source=token )
#create paymeny
payment = Payment()
payment.stripe_charge_id = charge['id']
payment.amount = amount
payment.save()
#assign payment to order
order.odered = True
order.payment = payment
order.save()
messages.success(self.request, "payment successful")
return redirect("/")
except stripe.error.CardError as e:
# Since it's a decline, stripe.error.CardError will be caught
body = e.json_body
err = body.get('error', {})
messages.warning(self.request, f"{err.get('message')}")
return redirect("/")
except stripe.error.RateLimitError as e:
# Too many requests made to the API too quickly
messages.error(self.request, f"{err.get('message')}")
return redirect("/")
except stripe.error.InvalidRequestError as e:
# Invalid parameters were supplied to Stripe's API
messages.error(self.request,"invalid parameters")
return redirect("/")
except stripe.error.AuthenticationError as e:
# Authentication with Stripe's API failed
# (maybe you changed API keys recently)
messages.error(self.request, "not authenticated")
return redirect("/")
except stripe.error.APIConnectionError as e:
# Network communication with Stripe failed
messages.error(self.request, "no network")
return redirect("/")
except stripe.error.StripeError as e:
# Display a very generic error to the user, and maybe send
# yourself an email
messages.error(self.request, "soemthng went wrong")
return redirect("/")
except Exception as e:
# Something else happened, completely unrelated to Stripe
messages.error(self.request, "soemthing went wrong. we re notified")
return redirect("/")

Receiving a CSV dataset in python Flask

I am having a python program that receives a CSV file (using pandas.read_csv option) from the user and returns the size of the CSV file as output.
My requirement is to have a GUI with an upload button and show the size of dataset in that GUI itself. I am a beginner in Python and Flask. Could anyone guide me here how to achieve this requirement in Python Flask?
I tried the following code but it says "Internal Server Error" and I don't know how to implement upload button.
import pandas as pd
from flask import Flask
app = Flask(__name__)
#app.route('/')
def data_shape():
data = pd.read_csv('iris.csv') # there should be an upload option / button for this dataset in the flask webservice
return data.shape
if __name__ == '__main__':
app.run(host='0.0.0.0')
I have to upload the csv file in the webservice and get the output of the python code in the webservice itself.
app.py
import os
import shutil
from flask import Flask, flash, request, redirect, render_template
from werkzeug.utils import secure_filename
from flask import Flask, session
from fastai.vision import *
basedir = os.path.abspath(os.path.dirname(__file__))
UPLOAD_FOLDER = os.path.join('static', 'csv')
app = Flask(__name__)
app.secret_key = "secret key"
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024
ALLOWED_EXTENSIONS = set(['csv','xls'])
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
#app.route('/')
def upload_form():
return render_template('index.html')
#app.after_request
def add_header(response):
"""
Add headers to both force latest IE rendering engine or Chrome Frame,
and also to cache the rendered page for 10 minutes.
"""
response.headers['X-UA-Compatible'] = 'IE=Edge,chrome=1'
response.headers['Cache-Control'] = 'public, max-age=0'
return response
#app.route('/', methods=['POST'])
def upload_file():
# shutil.rmtree(UPLOAD_FOLDER)
# os.mkdir(UPLOAD_FOLDER)
disp_div = 'none'
disp_div_tumor = 'none'
d = request.form.to_dict()
# print("dddd;",d)
button_name = 'None'
if (len(d)!=0):
button_name = list(d.items())[-1][0]
file = request.files['file']
print("file:",file)
if file.filename == '':
flash('No file selected for uploading','red')
# return redirect(request.url)
return render_template('index.html', disp_div = disp_div)
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
shutil.rmtree(UPLOAD_FOLDER)
os.mkdir(UPLOAD_FOLDER)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
flash('File successfully uploaded!', 'green')
print(UPLOAD_FOLDER)
print("==>",os.path.join(UPLOAD_FOLDER, sorted(os.listdir(app.config['UPLOAD_FOLDER']))[0]))
csv_file = pd.read_csv(os.path.join(UPLOAD_FOLDER, sorted(os.listdir(app.config['UPLOAD_FOLDER']))[0]))
csv_shape = csv_file.shape
return render_template('index.html', csv_shape=csv_shape)
# return redirect('/')
else:
flash('Allowed file types are txt, pdf, png, jpg, jpeg, gif', 'red')
# return redirect(request.url)
return render_template('index.html')
if __name__ == '__main__':
app.run(debug=False, port=5006)
## For deploying the app use `app.run(debug=False, host="0.0.0.0", port=80)`
templates/index.html
<link rel="stylesheet" type="text/css" href="/static/css/main.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="static/js/index.js"></script>
<script>
$(document).ready(function(){
$("#target").on('submit',function(){
// alert("It works");
});
});
</script>
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
</head>
<body>
<form id="target" method="post" enctype="multipart/form-data">
<div name ="up" class="upload-btn-wrapper">
<button name="upload" class="btn">Upload CSV File</button>
<input type="file" id="file" value="go" name="file" onchange="$('#target').submit();"/>
</div>
</form>
<p>
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
<div class=flashes>
{% for category_color, message in messages %}
<p class="error_text" style="color:{{ category_color }};width:500px;">{{ message }}</p>
{% endfor %}
</div>
{% endif %}
{% endwith %}
</p>
===> {{ csv_shape }}
</body>
</html>
static/css/main.css:
.upload-btn-wrapper {
position: absolute;
overflow: hidden;
display: inline-block;
top:0;
left:5%;
}
.btn {
width: 15vw;
height: 4vh;
padding: 0 0 2px;
font-size: 2.2vh;
/* font: 90% "Trebuchet MS", Tahoma, Arial, sans-serif; */
font-family: sans-serif;
font-weight: bold;
line-height: 32px;
text-transform: uppercase;
margin: 0.2em auto;
display: block;
outline: none;
position: relative;
cursor: pointer;
border-radius: 3px;
color: #ffffff;
text-shadow: 1px 1px #024bde;
border: 1px solid #507def;
border-top: 1px solid #2f73ff;
border-bottom: 1px solid #2a67ff;
box-shadow: inset 0 1px #4a82ff, inset 1px 0 #2653b9, inset -1px 0 #2d69e8, inset 0 -1px #4372e8, 0 2px #1c3d9e, 0 6px #2553a2, 0 4px 2px rgba(0,0,0,0.4);
background: -moz-linear-gradient(top, #cae285 0%, #a3cd5a 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#cae285), color-stop(100%,#a3cd5a));
background: -webkit-linear-gradient(top, #6292ff 0%,#2b6cff 100%);
background: -o-linear-gradient(top, #cae285 0%,#a3cd5a 100%);
background: -ms-linear-gradient(top, #cae285 0%,#a3cd5a 100%);
background: linear-gradient(top, #cae285 0%,#a3cd5a 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#cae285', endColorstr='#a3cd5a',GradientType=0 );
background-color: #1c3c9e;
}
.btn::-moz-focus-inner{border:0}
.btn:active {
/*top: 3px;*/
/* border: 1px solid #88A84E;
border-top: 1px solid #6E883F;
border-bottom: 1px solid #95B855;
background: #A7CF5F;*/
box-shadow: inset 0 1px 2px #779441;
transform: translateY(3px);
}
.pred {
position: absolute;
left: 10%;
bottom: 0;
}
.upload-btn-wrapper input[type=file] {
font-size: 100px;
position: absolute;
left: 0;
top: 0;
opacity: 0;
}
.submit_btn {
border: 2px solid gray;
color: gray;
background-color: white;
padding: 8px 20px;
border-radius: 8px;
font-size: 20px;
font-weight: bold;
}
.error_text {
position: absolute;
top: 2.7vh;
font-weight: bold;
font-size: 2vh;
left: 5%;
}
Directory structure:
|-- fapp.py
|-- static
| |-- css
| | `-- main.css
| `-- csv
`-- templates
`-- index.html
Edit:

Categories

Resources