REST API ajax not working - javascript

I am working on a school project where I have to program a REST API application that interacts with a database with basic POST and DELETE operation:
Here is my Python Flask file:
from flask import Flask, render_template, redirect, url_for, jsonify, request, Response, abort
from flask_bootstrap import Bootstrap
import dbinteraction
app = Flask(__name__)
Bootstrap(app)
#app.route('/')
def hello_world():
return redirect(url_for('index'))
#app.route('/index')
def index():
return render_template('index.html')
#app.route('/allrecipes')
def allrecipes():
return render_template('allrecipes.html')
#app.route('/ingredients')
def ingredients():
return render_template('ingredients.html')
#app.route('/api/v1.0/recipes', methods=['GET'])
def get_recipes():
# init
recipes = []
# get the task list from the db
recipes_list = dbinteraction.getRecipes()
# prepare the task list for jsonify
for item in recipes_list:
recipe = prepare_for_json(item)
recipes.append(recipe)
# return the task data
return jsonify({'recipes': recipes})
#app.route('/api/v1.0/ingredients', methods=['GET'])
def get_ingredients():
# init
ingredients = []
# get the user_ingredients list from the db
ingredients_list = dbinteraction.getIngredients()
# prepare the user_ingredients list for jsonify
for item in ingredients_list:
ingredient = prepare_for_json_ingredient(item)
ingredients.append(ingredient)
# return the ingredients data
return jsonify({'ingredients': ingredients})
#app.route('/api/v1.0/ingredients', methods=['POST'])
def insert_ingredient():
# get the request body
add_request = request.json
# check whether an ingredient is present or not
if (add_request is not None) and ('name' in add_request) and ('quantity' in add_request):
text = add_request['name']
quantity = add_request['quantity']
# insert in the database
dbinteraction.insertIngredients(text, quantity)
return Response(status=201)
# return an error in case of problems
abort(403)
#app.route('/api/v1.0/ingredients/<string:ing_name>', methods=['DELETE'])
def delete_ingredient(ing_name):
# delete the ingredient
ingredient = dbinteraction.removeIngredient(str(ing_name))
return Response(status=200)
def prepare_for_json(item):
"""
Convert the recipe in a dictionary for easing the JSON creation
"""
recipe = dict()
recipe['name'] = item[0]
recipe['link'] = item[1]
recipe['difficulty'] = item[2]
return recipe
def prepare_for_json_ingredient(item):
"""
Convert the ingredient in a dictionary for easing the JSON creation
"""
ingredient = dict()
ingredient['name'] = item[0]
ingredient['quantity'] = item[1]
return ingredient
if __name__ == '__main__':
app.run(debug=True)
I also programmed and tested the dbinteraction functions for the database and they work fine. My problem is in the ingredients.html part. I load and see the page as I want, a modifiable list of ingredients with the delete button. But when I click on the delete I get a Uncaught ReferenceError: (name of the ingredient) is not defined at HTMLAnchorElement.onclick
This are my html and javascript files:
{% extends "bootstrap/base.html" %}
{% block title %}All recipes page{% endblock %}
{% block styles %}
{{super()}}
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.12/css/all.css"
integrity="sha384-G0fIWCsCzJIMAVNQPfjH08cyYaUtMwjJwqiRKxxE/rx96Uroj1BtIQ6MLJuheaO9" crossorigin="anonymous">
{% endblock %}
{% block scripts %}
{{ super() }}
<script src="{{ url_for('static', filename='kima2js.js') }}"></script>
{% endblock %}
{% block content %}
<div class="container" style="text-align: center">
<h1><i class="fas fa-utensils" style=""></i><br>
Insert an ingredient:
</h1>
<div id="ingredients_list" class="form-inline"></div>
<div id="insertingredient">
<form id="addForm"class="form-inline" method="POST">
<div class="form-group">
<label for="ingredientName">Ingredient:</label>
<input type="text" id="ingredientName" class="form-control" name="name"/>
</div>
<div class="form-group">
<label for="ingredientQuantity">Quantity:</label>
<input type="text" id="ingredientQuantity" class="form-control" name="quantity"/>
</div>
<button type="submit" class="btn-sm">Add</button>
</form>
</div>
</div>
{% endblock %}
... the javascript:
function addIngredient() {
$("#ingredients_list ul").empty();
$("#ingredientName").val('');
$("#ingredientQuantity").val('');
getIngredients();
}
function getIngredients() {
$.getJSON("http://127.0.0.1:5000/api/v1.0/ingredients", function(data){
var ingredients = data["ingredients"];
var len = ingredients.length;
for(var i = 0 ; i<len ; i++) {
var t = ingredients[i];
$("#ingredients_list ul").append("<li class='list-group-item list-group-item-text'>"+t.name+" "+t.quantity
+" <a class='delete btn btn-default' onclick='deleteIngredient("+ t.name +")'>" +
" <span class='glyphicon glyphicon glyphicon-remove'></span>Delete</a></li>");
}
});
}
function deleteIngredient(ing_name) {
$.ajax("/api/v1.0/ingredients/"+ing_name,
{
method: 'DELETE',
success: function (status) {
// update the list of printed ingredients: called when the DELETE is complete
getIngredients();
}
}
);
}
$(document).ready(function () {
$("#ingredients_list").append("<ul></ul>");
$("#ingredients_list ul").empty();
getIngredients();
$("#addForm").submit( function(){
var name = $("#ingredientName").val();
var quantity = $("#ingredientQuantity").val();
var ingredient = {'name': name, 'quantity': quantity};
var json = JSON.stringify(ingredient);
$.post({
"url": "http://127.0.0.1:5000/api/v1.0/ingredients",
"data": json,
"contentType":"application/json",
"success": addIngredient
});
return false;
});
});
I can't see what I am doing wrong. My only guesses are on the onclick part. Because I have tested singularly all the other pieces of code in previous labs

You just need to make sure that the value of ing_name is in quotes when you write it as a parameter to onclick, as follows:
$("#ingredients_list ul").append("<li class='list-group-item list-group-item-text'>"+t.name+" "+t.quantity
+" <a class='delete btn btn-default' onclick='deleteIngredient(\""+ t.name +"\")'>" +
" <span class='glyphicon glyphicon glyphicon-remove'></span>Delete</a></li>");
Otherwise javascript thinks ing_name is a variable name (and the variable is not defined).

Related

Like button using Ajax not working in Django project

I am stuck on a problem I am having trying to implement a 'Like' button into my django application.
I have the functionality working for the models, and even in the html template the code works if I manually add a like from a user.
It seems like my Ajax may be the issue, but I can't seem to figure out why.
Here is my models.py:
class Post(models.Model):
direct_url = models.URLField(unique=True)
post_url = models.URLField()
post_title = models.CharField(max_length=300)
time_posted = models.DateTimeField(default=timezone.now)
user = models.ForeignKey(User, on_delete=models.CASCADE)
class Like(models.Model):
liker = models.ForeignKey(User, on_delete=models.CASCADE)
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='likes')
date_created = models.DateTimeField(default=timezone.now)
def save(self, *args, **kwargs):
super(Like, self).save(*args, **kwargs)
And here is my views.py
class PostListView(LoginRequiredMixin, generic.ListView):
model = Post
template_name = 'homepage/home.html'
ordering = ['-time_posted']
context_object_name = 'posts'
paginate_by = 6
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['now'] = datetime.now()
context['likesbyuser'] = Like.objects.filter(liker=self.request.user)
return context
def likePost(request):
if request.method == 'GET':
post_id = request.GET['post_id']
likedpost = Post.objects.get(pk=post_id) # getting the liked post
if Like.objects.filter(post=likedpost, liker=request.user).exists():
Like.objects.filter(post=likedpost, liker=request.user).delete()
else:
m = Like(post=likedpost, liker=request.user) # creating like object
m.save() # saves into database
return HttpResponse(likedpost.likes.count())
else:
return HttpResponse("Request method is not a GET")
This is part of the template, where I am putting the buttons to use the Ajax which should call the like function:
{% for i in post.likes.all %}
{% if user == i.liker %}
<a class='likebutton' data-catid="{{ post.id }}"><i id='like{{ post.id }}' class="btn fas fa-heart fa-lg post-buttons "></i></a>
{% elif forloop.last %}
<a class='likebutton' data-catid="{{ post.id }}"><i id='like{{ post.id }}' class="btn far fa-heart fa-lg post-buttons "></i></a>
{% endif %}
{% empty %}
<a class='likebutton' data-catid="{{ post.id }}"><i id='like{{ post.id }}' class="btn far fa-heart fa-lg post-buttons "></i></a>
{% endfor %}
{% endfor %}
And here is the Ajax code I am adding to the base.html in script tags.
<script type="text/javascript">
$('main').on('click', '.likebutton', function(){
var catid;
catid = $(this).attr("data-catid");
$.ajax(
{
type:"GET",
url: "/likepost/",
data:{
post_id: catid
},
success: function(data){
if(data==0){
$('.like' + catid).toggle();
$('#like' + catid).toggleClass("far fas");
$('#likecount' + catid).html('');
console.log(data+'if');
}
else if(data==1){
if($('.like' + catid).is(":hidden"))
{
$('.like' + catid).toggle();
}
$('#like' + catid).toggleClass("far fas");
$('#likecount' + catid).html(data + ' like');
console.log(data+'elseif');
}
else{
$('#like' + catid).toggleClass("far fas");
$('#likecount' + catid).html(data + ' likes');
console.log(data+'else');
}
}
})
});
</script>
I have tried adding event.preventDefault(); to the ajax call, but that did not fix my issue.
I found the issue.
I was pointing the Ajax code at "main" as seen in the following snippet:
...
<script type="text/javascript">
$('main').on('click', '.likebutton', function(){
...
My issue was that I forgot to surround the block with the main tag when I ported this project over.
In my base.html I added the following code:
<main role="main" class="container h-100">
{% block content %}
{% endblock content %}
</main>
This fixed the issue.

Comments are not saving from frontend in django

Hi everyone the comments are not working with CBV my form not even saving the comment. here is my code i will love if anyone help me with this.my models.py is
class Product(models.Model):
title = models.CharField(max_length=110)
slug = models.SlugField(blank=True, unique=True)
price = models.DecimalField(decimal_places=2, max_digits=6)
discount_price=models.FloatField(blank=True, null=True)
size = models.CharField(choices=SIZE_CHOICES, max_length=20)
color = models.CharField(max_length=20, blank=True, null=True)
image = models.ImageField(upload_to=upload_image_path)
description = models.CharField(max_length=1000)
featured = models.BooleanField(default=False)
author = models.ForeignKey(User, on_delete=models.CASCADE)
time_stamp = models.DateTimeField(auto_now_add=True)
objects=ProductManager()
def get_absolute_url(self):#i use this in product_list.html to go to detail page
#return "/product/{slug}".format(slug=self.slug)
return reverse("products:detail", kwargs={"slug" : self.slug})
def __str__(self):
return str(self.title)
#property
def name(self): #sometime in html i say name istead of title so to make it work i wrote this
return self.title
def product_pre_save_reciever(sender, instance, *args, **kwargs):#i inherit unique slug generator from utils to here so when i create aa new instance it slug automatically generate. and i i create two t shirts it give a random straing to tshirt 2nd slug
if not instance.slug:
instance.slug=unique_slug_generator(instance)
pre_save.connect(product_pre_save_reciever, sender=Product)
class Comment(models.Model):
product=models.ForeignKey(Product , related_name="comments", on_delete=models.CASCADE)
name = models.CharField(max_length=255)
body=models.TextField()
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
return '%s - %s'%(self.product.title, self.name)
my forms.py is:
from django import forms
from .models import Comment
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ['name', 'body']
widgets ={
'name':forms.TextInput(attrs={'class':'form-control'}),
'body':forms.Textarea(attrs={'class':'form-control'}),
}
the views.py is:
class CommentCreateView(CreateView):
model = Comment
form_class = CommentForm
template_name = 'add-comment.html'
# fields = '__all__'
def form_valid(self, form):
form.instance.product_id = self.kwargs['pk']
return super().form_valid(form)
success_url = reverse_lazy('list')
my add-comment.html is:
{% extends "base.html"%}
{% load crispy_forms_tags%}
{% block content %}
<h2 class="text-center">comment here...</h2>
<div class="col-md-6 offset-md-3">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
{{form|crispy}}
</fieldset>
<!-- <div class="form-group"><button class="btn btn-outline-info" type="submit">Pubmit</button>-->
<!-- </div>-->
<!-- <input type="submit" value="Submit" class="btn btn-secondary">-->
<button class="btn btn-secondary">Add comment</button>
</form>
</div>
{% endblock %}
and my urls.py is:
urlpatterns = [
# path('featured/' , ProductFeaturedListView.as_view()),
#path('featured/<int:pk>' , ProductFeaturedDetailView.as_view()),
path('' , ProductListView.as_view(), name= "list"),
path('new/' , ProductCreateView.as_view() , name="product-create"),
path('<slug:slug>/update/' , ProductUpdateView.as_view() , name="product-update"),
path('<slug:slug>/delete/' , ProductDeleteView.as_view() , name="product-delete"),
#path('product-fbv/' , product_list_view),
#path('product/<int:pk>' , ProductDetailView.as_view()),
path('<slug:slug>/comment' , CommentCreateView.as_view() , name="add-comment"),
path('<slug:slug>' , ProductDetailSlugView.as_view() , name="detail"),
# path('product-fbv/<int:pk>' , product_detail_view),
]
and the error comes when I hit post comment is:
The problem comes from the fact you don't provide any pk keyword argument to your view.
From the urls.py, I can see you have a slug kwargs though. You can then identify the matching product with its slug.
In your views.py, replace:
form.instance.product_id = self.kwargs['pk']
by
form.instance.product = Product.objects.get(slug=self.kwargs['slug'])
Explanation:
Here you want to associate your comment with the matching product. So, for that, you use NameOfModel.objects.get(query), which returns one single instance of your model (here Product), matching the query. In your case the only way to retrieve the object is getting the keyword argument slug from your url and search it on your Product slug field, so here the query is slug=self.kwargs['slug'].

In my Django Project, I am Trying to execute the python method in by hitting the html button

When I am hitting the edit button of my studentUpdate.html file then I am getting following error:-
NoReverseMatch at /studentUpdate/
Reverse for 'update_student' with no arguments not found. 1 pattern(s) tried: ['update_student/(\d+)/$']
Someone help me.
<!-- studentUpdate.html -->
{% extends 'app.html' %}
{% block body %}
<div>
<div class="alert alert-info">All Students</div>
<button id="show_book" type="button" class="btn btn-success">
<span class="glyphicon glyphicon-circle-arrow-left">
</span> Back
</button>
<div id="edit_form"></div>
<div id="book_form" >
<div class="col-lg-3"></div>
<div class="col-lg-6">
<form id="form" method="POST" action="{% url 'students' %}">
{% csrf_token %}
<div class="form-group">
<label >Student ID:</label>
<input type="text" name="sid" required="required" class="form-control"/>
</div>
<div class="form-group">
<label>First name:</label>
<input type="text" name="firstname" class="form-control"/>
</div>
<div class="form-group">
<label>Last name:</label>
<input type="text" name="lastname" class="form-control"/>
</div>
<div class="form-group">
<label>Department:</label>
<input type="text" name="department" class="form-control" required="required"/>
</div>
<div class="form-group">
<label>Section:</label>
<input type="text" name="section" class="form-control"/>
</div>
<div class="form-group">
<label>Year:</label>
<input type="text" name="year" class="form-control"/>
</div>
<div class="form-group">
<button name="save_book" id="save_book" type="submit" class="btn btn-primary" href="{% url 'update_student' %}"><span
class="glyphicon glyphicon-save"></span>
Update
</button>
</div>
</form>
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
<script>
$(document).ready(function ()
{
$('#table').DataTable();
});
$(document).ready(function () {
$('#add_book').click(function () {
$(this).hide();
$('#show_book').show();
$('#book_table').slideUp();
$('#book_form').slideDown();
$('#show_book').click(function () {
$(this).hide();
$('#add_book').show();
$('#book_table').slideDown();
$('#book_form').slideUp();
});
});
});
$('.editButton').on('click', function () {
var id = $(this).attr('data-id');
$.ajax({
url: 'http://localhost:8000/edit_book/' + id,
method: 'GET'
}).success(function (response) {
{# alert(response.title);#}
$('#form')
.find('[name="title"]').val(response.title).end()
.find('[name="description"]').val(response.description).end()
.find('[name="author"]').val(response.author).end()
.find('[name="quantity"]').val(response.quantity).end();
document.getElementById('save_book').innerText = 'Update';
$(this).hide();
$('#show_book').show();
$('#book_table').slideUp();
$('#book_form').slideDown();
$('#add_book').hide();
$('#show_book').click(function () {
$(this).hide();
document.getElementById('form').reset();
$('#add_book').show();
$('#book_table').slideDown();
$('#book_form').slideUp();
});
});
});
</script>
{% endblock %}
Here is my Url.py file
from django.conf.urls import url, include
from . import views
from django.urls import path, re_path
urlpatterns = [
url(r'^index$', views.index),
url(r'^books$', views.books, name="books"),
url(r'^categories$', views.categories, name="categories"),
url(r'^students$', views.students, name="students"),
url(r'^returning$', views.returning, name="returning"),
url(r'^borrow$', views.borrow, name="borrow"),
url(r'^edit_book/(\d+)/$', views.edit_book, name="edit_book"),
url(r'^edit_category/(\d+)/$', views.edit_category, name="edit_category"),
url(r'^delete_book/(\d+)/$', views.delete_book, name="delete_book"),
url(r'^delete_category/(\d+)/$', views.delete_category, name="delete_category"),
url(r'^delete_student/(\d+)/$', views.delete_student, name="delete_student"),
#url(r'^studentUpdate/(\d+)/$', views.studentUpdate, name="studentUpdate"),
path('studentUpdate/', views.studentUpdate),
url(r'^update_student/(\d+)/$', views.update_student, name="update_student"),
]
Here is my views.py file
from django.shortcuts import render, redirect
from django.http import JsonResponse
from django.db.models import Sum
from datetime import date
from datetime import datetime
from django.contrib.auth.decorators import login_required
from django.http import HttpResponse
# Create your views here.
from library.models import Book, Category, Student, Borrow
import playsound
from django.template import loader
def index(request):
return render(request, "index.html", {})
def categories(request):
if request.method == "POST":
title = request.POST['title']
Category(title=title).save()
return redirect('/categories')
categories = Category.objects.all()
return render(request, "category.html", {"categories": categories})
def delete_category(request, id):
category = Category.objects.filter(id=id)
category.delete()
return redirect('/categories')
def edit_category(request, id):
category = Category.objects.filter(id=id).get()
return JsonResponse({'title': category.title})
def books(request):
if request.method == "POST":
title = request.POST['title']
author = request.POST['author']
cat = Category.objects.get(id=int(request.POST['category_id']))
description = request.POST['description']
available = int(request.POST['quantity'])
book = Book(title=title, author=author, description=description, available=available)
book.save()
if book.categories.add(cat):
return redirect('/books')
books = Book.objects.all()
categories = Category.objects.all()
return render(request, "books.html", {"books": books, "categories": categories})
def edit_book(request, id):
book = Book.objects.filter(id=id).get()
return JsonResponse(
{'title': book.title, 'author': book.author, 'description': book.description, 'available': book.available})
def delete_book(request, id):
book = Book.objects.filter(id=id).get()
book.delete()
return redirect("/books")
def students(request):
if request.method == "POST":
sid = request.POST["sid"]
firstname = request.POST["firstname"]
lastname = request.POST["lastname"]
department = request.POST["department"]
section = request.POST["section"]
year = request.POST["year"]
student = Student(student_id=sid, firstname=firstname, lastname=lastname, department=department,
section=section, year=year)
student.save()
return redirect("/students")
students = Student.objects.all()
return render(request, "students.html", {"students": students})
def borrow(request):
if request.method == "POST":
student_id = request.POST['student_id']
student = Student.objects.get(id=student_id)
status = "Borrowed"
books_id = request.POST.getlist('selector')
for book_id in books_id:
book = Book.objects.get(id=book_id)
b = Borrow(qty=1, status=status)
b.save()
b.student.add(student)
b.book.add(book)
return redirect("/borrow")
students = Student.objects.all()
books = Book.objects.all()
datas = []
for book in books:
left = Borrow.objects.filter(status="Borrowed", book__title=book.title).aggregate(Sum('qty'))
if left['qty__sum'] is None:
l = 0
else:
l = int(left['qty__sum'])
datas.append(book.available - l)
return render(request, "borrow.html", {"datas": zip(books, datas), "students": students})
def delete_student(request, id):
student = Student.objects.filter(id=id).get()
student.delete()
return redirect('/students')
def returning(request):
if request.method == "POST":
b_id = int(request.POST["borrow_id"])
borrow = Borrow.objects.get(id=b_id)
borrow.date = datetime.now()
borrow.status = "Returned"
borrow.save()
return redirect('/returning')
borrows = Borrow.objects.all()
return render(request, "return.html", {"borrows": borrows})
def studentUpdate(request):
template = loader.get_template('studentUpdate.html')
return HttpResponse(template.render())
def update_student(request,id):
return redirect('/students')
First, if you want to submit a form (which already has a target url, here it is students), you do not need to specify any href when setting your submit button, you have to check that.
Then, what does your error message say? It says you want to use a url shortname that does not refer to anything in your urls.py file. So, you have to check this out precisely. It does not have anything related to the form itself: just loading your page on a GET request will generate an error, because Django can not understand what you want to achieve.
It is not clear for us to help, because you have too many confusing definitions of what you try to achieve. Just show one solution at a time, only one update_student view, same goes for urls. Comment everything looking like "update_student" except this one: url(r'^update_student/(\d+)/$', views.update_student, name="update_student").
Finally, your error message indicates that you are not passing any argument to your url, but arguments are expected (see the (\d+) in your url definition). So, make a few more research to understand how to pass arguments to your {% url ... %} stuff, you are close to have something not generating any error on a GET call. Good luck! :-)
The problem is in this line:
<button name="save_book" id="save_book" type="submit" class="btn btn-primary" href="{% url 'update_student' %}">
<span class="glyphicon glyphicon-save"></span>
Update
</button>
Because the way you have defined the url for the update_student function it must be called with some argument of integer type.
For example:
Click Me
In the above example the integer 5 is passed as an argument.
Because you are not passing any argument with the update_student url so only you are getting the error which you mentioned in the question.
I hope it will help you!!

How to create Flask-Stripe Checkout and Charge for the multiple items

I am building an integration with Stripe by following the examples in its documentation, but I can't understand the part of creating a Charge for more than one product.
I was looking all over Stripe's docs and was searching for any articles / forums about the similar issue but was unable to find anything. I'd be very grateful to either some links to the articles on this matter or any tips to help me to understand how to solve it.
Here's a server side code:
```python
#app.route("/checkout", methods=["GET", "POST"])
def checkout():
if request.method == "POST":
# Process a JSON string with a checkout information:
# { item_id: item_quantity, ... }
# Build the SQL query based on it
items = {}
shopping_cart = request.form["cart_checkout"]
shopping_cart = shopping_cart.lstrip("{")
shopping_cart = shopping_cart.rstrip("}")
shopping_cart = shopping_cart.split(",")
sqlQuery = "SELECT * FROM Items WHERE item_id IN ("
for KeyValPair in shopping_cart:
Key = KeyValPair.split(":")[0]
Key = Key.strip('"')
sqlQuery = sqlQuery + Key + ","
Value = KeyValPair.split(":")[1]
items[Key] = Value
sqlQuery = sqlQuery.rstrip(",")
sqlQuery = sqlQuery + ") ORDER BY item_id ASC"
cart_items = sql_select(sqlQuery)
# Add a column about the quantity of items
for item in cart_items:
item["quantity"] = items[item["item_id"]]
# Build a Stripe checkout list
line_items_list = []
for item in cart_items:
line_item = {}
line_item["name"] = item["item_name"]
line_item["description"] = item["item_description"]
line_item["amount"] = item["price"]
line_item["currency"] = "usd"
line_item["quantity"] = item["quantity"]
line_items_list.append(dict(line_item))
stripe_session = stripe.checkout.Session.create(
submit_type="pay",
payment_method_types=["card"],
line_items=line_items_list,
success_url='https://example.com/success',
cancel_url='https://example.com/cancel',
)
return render_template("checkout.html",
stripe_id=stripe_session.id,
stripe_pk=stripe_keys["PUBLIC_KEY"])
return redirect("/")
```
And here's a part of HTML template:
```html
<form action="/checkout" method="post" id="form_checkout" onsubmit="return cart_info()"
...
<input type="hidden" name="cart_checkout" id="checkout_info" value="{{ cart_checkout }}">
<script
src="https://checkout.stripe.com/checkout.js" class="stripe-button"
data-key="{{ stripe_pk }}"
data-name="Company Name"
data-image="https://stripe.com/img/documentation/checkout/marketplace.png"
data-description="A description of the product or service being purchased"
data-amount="999"
data-shipping-address="true"
data-zip-code="true"
data-allow-remember-me="true"
data-panel-label="Pay"
data-label="Checkout"
data-locale="auto">
</script>
</form>
```
If I do a simple example of Charge from Stripe docs, like this:
```python
#app.route('/charge', methods=['POST'])
def charge():
# Amount in cents
amount = 500
customer = stripe.Customer.create(
email='customer#example.com',
source=request.form['stripeToken']
)
charge = stripe.Charge.create(
customer=customer.id,
amount=amount,
currency='usd',
description='Flask Charge'
)
return render_template('charge.html', amount=amount)
```
Then I can create without any issues a successful test Charge, it displays with the success label in my Stripe's dashboard. If I use stripe.checkout.Session.create, Stripe dashboard properly creates an incomplete record about my Checkout session with the selected list of items, but I've no idea how to proceed from there to finalise the Charge for them.
As often happens, when I start asking questions, I eventually find the answers on my own, lol. I've had a "checkout.html" template but it didn't work, and no errors were displaying, so I assumed that I was missing some more code required for it all to work.
As it happened, all I was missing, was "" in a line of code. Here's a working Checkout session with the addition of a bit of JavaScript:
{% extends "layout.html" %}
{% block title %}Checkout{% endblock %}
{% block head %}
<script src="https://js.stripe.com/v3/"></script>
{% endblock %}
{% block main %}
<!-- Main content -->
<div class="wrapper main-content">
{% with messages = get_flashed_messages(with_categories=true) %}
{% for category, message in messages %}
<div class="alert alert-{{ category }}">{{ message }}</div>
{% endfor %}
{% endwith %}
<h2 class="section-header">Checkout</h2>
<p id="result_msg"></p>
<button onclick="checkout()">Checkout</button>
</div>
<script type="text/javascript">
function checkout() {
var stripe = Stripe("{{ stripe_pk }}");
stripe.redirectToCheckout({
// Make the id field from the Checkout Session creation API response
// available to this file, so you can provide it as parameter here
// instead of the {{CHECKOUT_SESSION_ID}} placeholder.
sessionId: "{{CHECKOUT_SESSION_ID}}"
}).then(function (result) {
// If `redirectToCheckout` fails due to a browser or network
// error, display the localized error message to your customer
// using `result.error.message`.
document.getElementById("result_msg").innerHTML = result.error.message;
});
}
</script>
{% endblock %}

Possible to incorporate select tag in django form?

I have a django form being rendered on an html page, and I have a select dropdown menu which performs a filtering function. I was wondering if it was possible to incorporate this select tag as part of my form? I'd like the select tag to be part of routestep_form.
<center>
<form class ="subtitle" method = 'POST' action="{% url 'buildpage:partrequestinfo' %}" enctype="multipart/form-data">{% csrf_token %}
{{routestep_form.as_p}}
<select name = "myselect" id="id_step" onchange="getOptions(this.value)">
<option value="-----">-----</option>
{% for step in steps %}
<option value="{{ step }}">{{ step }}</option>
{% endfor %}
</select>
<br/><br/>
<select id="id_step_option">
<option value="-----">-----</option>
</select>
<input type='submit' value='Next'/>
</form>
</center>
My Form:
class RouteStepForm(forms.ModelForm):
class Meta:
model = RouteStep
fields = '__all__'
widgets = {
'step': Select,
'step_option': Select,
}
error_messages = {
NON_FIELD_ERRORS: {
'unique_together': "%(RouteStep)s %(description)s are not unique.",
}
}
Views: The other forms are forms I had on the same page, my main focus though is on RouteStepForm.
def partrequestinfo(request):
steps = Step.objects.all()
if not request.user.is_staff or not request.user.is_superuser:
raise Http404
req_form = PartRequestForm(request.POST or None, request.FILES or None)
step_form = StepForm(request.POST or None, request.FILES or None)
stepoption_form = StepOptionForm(request.POST or None, request.FILES or None)
routestep_form = RouteStepForm(request.POST or None, request.FILES or None)
if req_form.is_valid() and step_form.is_valid() and stepoption_form.is_valid() and routestep_form.is_valid():
instance = req_form.save(commit=False)
instance.user = request.user
instance.save()
step = step_form.save(commit=False)
step.save()
stepoption = stepoption_form.save(commit=False)
stepoption.save()
routestep = routestep_form.save(commit=False)
routestep.save()
messages.success(request, "Successfully Created")
return HttpResponseRedirect(instance.get_absolute_url())
else:
context = {
"req_form": req_form,
"step_form": step_form,
"stepoption_form": stepoption_form,
"routestep_form": routestep_form,
"steps": steps,
}
return render(request, "buildpage/partrequestinfo.html", context)
Models:
class Step(models.Model):
name = models.CharField(_('Step Name'), max_length=100, default='')
def __unicode__ (self):
return self.name
class StepOption(models.Model):
step = models.ForeignKey(Step, related_name = 'Step', null = True)
name = models.CharField(_('Step Option'), max_length=100, default='')
def __unicode__ (self):
return self.name + " - " + self.step.name
class RouteStep(models.Model):
step_number = models.PositiveIntegerField(_('Step Number'), default = 0)
step = models.ForeignKey(Step, related_name = 'Step+', null = True)
step_option = models.ForeignKey(StepOption, related_name = 'StepOption', null=True)
def __unicode__ (self):
return self.step_option
Try:
class RouteStepForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(forms.ModelForm, self).__init__(*args, **kwargs)
self.fields['step'].widget.choices=[ query.name for query in Step.objects.all()])
If it does not work, please post your template code that show up.
EDIT
I edit my answer, and also find this helpful.Why do I get an object is not iterable error? and this Getting object not iterable error in django form.
Another solution will be Can not iterate a ChoiceField with Select as widget

Categories

Resources