update sqlite database in python after the item from dropdown suggestions selected - python

My program must update table "idlist" in python after the item was selected from drop down suggestions in js. User selects the item, after that POST request in python adds it to the "idlist" table.
As I run the program I get the following error message:
I am grateful for your ideas and suggestions:
Here is my python code:
def search():
"""Search for books that match query"""
if request.method == "GET":
if not request.args.get("q"):
return render_template("adjust.html")
else:
q = request.args.get("q") + "%"
books = db.execute("SELECT Title, Author FROM book WHERE Title LIKE :q OR Author LIKE :q", q=q)
return jsonify(books)
if request.method == "POST" and request.form.get("title"):
Title = request.form.get("title")
insert_book = db.execute("INSERT INTO idlist (id,Title1, Status) VALUES (:id, :Title1, :Status)", id=session["user_id"], Title1=Title, Status="Not started")
return redirect("/")
return render_template("adjust.html")
Here is html:
{% extends "layout.html" %}
{% block title %}
Add your Book
{% endblock %}
{% block main %}
<form action="/adjust" method="POST">
<div class="form-group">
<p>Choose your Book</p>
<label class="sr-only" for="q">Title, Author</label>
<input class="form-control" id="q" placeholder="Title, Author" name="title" type="text" autocomplete="off" />
</div>
<button class="btn btn-primary" type="submit">Add</button>
</form>
{% endblock %}
Here is js:
function configure()
{
// Configure typeahead
$("#q").typeahead({
highlight: false,
minLength: 1
},
{
display: function(suggestion) { return suggestion.Title; },
limit: 10,
source: search,
templates: {
suggestion: Handlebars.compile(
"<div>"+
"{{Title}}, {{Author}}" +
"</div>"
)
}
});
// Give focus to text box
$("#q").focus();
}
// Search database for typeahead's suggestions
function search(query, syncResults, asyncResults)
{
// Get places matching query (asynchronously)
let parameters = {
q: query
};
$.getJSON("/adjust", parameters, function(data, textStatus, jqXHR) {
// Call typeahead's callback with search results (Author Title)
asyncResults(data);
});
}
$(document).ready(function() {
configure();
});

Don't use Ajax to Add new book it will make user confused because he don't know if it was added to the idlist or not, use the Form POST instead.
in script.js remove the following block
$("#q").on('typeahead:selected', function a(eventObject, suggestion, name) {
...
...
});
and to add selected item to the input form, replace
display: function(suggestion) { return null; },
with
display: function(suggestion) { return suggestion.Title; },
to make form POST, in adjust.html replace
<form action="/adjust">
....
<input class="form-control" id="q" placeholder="Title, Author" type="text"/>
with
<form action="/addbook" method="POST">
....
<input class="form-control" id="q" placeholder="Title, Author" name="title" type="text" autocomplete="off" />
And the addBook() method
#app.route("/addbook", methods=["GET", "POST"])
def addbook():
"""Add selected book"""
if request.method == "POST" and request.form.get("title"):
Title = request.form.get("title")
insert_book = db.execute("INSERT INTO idlist (id,Title1, Status) VALUES (:id, :Title1, :Status)", id=session["user_id"], Title1=Title, Status="Not started")
return redirect("/")
# no "title" in the form, return to Add new book page
return redirect("/adjust")

Related

Flask route not accessing statement: if request.method == 'POST' provided by ajax object, but works fine on another route

I am struggling to understand why when I have 2 routes why the if request.method == "POST": in #views.route("/", methods =["GET","POST"]) is able to grab the data, but another route: #views.route("/splits", methods =["GET", "POST"]) does not.
Both route have seperate templates that inherit from index.html, when I submit the form the fisrt route's function returns the data as expected and updates the DOM. When I submit the form from the template rendered from #views.route("/splits", methods =["GET","POST"]) (splitAnalysis.html) the url redirects to something like: http://127.0.0.1:7000/views/swrsplits?swrNo=12345&fileLable=testing1&folderName=test2, and it doesn't seem like any data is returned.
Edit to add only the most relevent portions of my files
app.py:
from flask import Flask
from views import views
app = Flask(__name__)
app.register_blueprint(views, url_prefix="/views")
if __name__ == '__main__':
app.run(debug=True, port=7000)
Views.py:
from flask import Blueprint, render_template, request, jsonify, send_from_directory, send_file
from probe_pull import probe_puller
from datetime import date
from pathlib import Path
import os
views = Blueprint(__name__, "views")
#views.route("/", methods =["GET","POST"])
def trend():
if request.method == "POST":
return callProbeExtract(request.form)
return render_template("Trends.html")
#views.route("/swrsplits", methods =["GET", "POST"])
def swrPull():
if request.method == "POST":
print("hey your in")
returnString = f'{request.form["_swrNo"]}__{request.form["_fileLable"]}'
_outPutFileName = request.form["_folderName"]
return jsonify({'output':returnString, 'fileName':_outPutFileName})
return render_template("splitAnalysis.html")
index.html - the template the others inherit from (only showing the JQuery):
<script type="text/javascript">
function primeDOM(firstPass, fileName, filePath, output) {
if (firstPass) {
...Does stuff...
}
$(document).ready(function () {
var zipName = {
fileName: "",
filePath: "",
};
var firstPass = true;
$("#spinner").hide();
$("#btn-text-load").hide();
var currForm = $("#formHolder").children("form").attr("id");
$(currForm).on("submit", function (e) {
if ((currForm = "form")) {
var ajaxData = {
_mistiList: $("#mistiId").val(),
_familyName: $("#familyName").val(),
_logPoint: $("#logPoint").val(),
_opn: $("#opn").val(),
_daysBack: $("#daysBack").val(),
_daysStart: $("#daysStart").val(),
_folderName: $("#folderName").val(),
};
var ajaxUrl = "{{url_for('views.trend')}}";
} else if ((currForm = "formSWR")) {
var ajaxData = {
_swrNo: $("#swrNo").val(),
_fileLable: $("#fileLable").val(),
_folderName: $("#folderName").val(),
};
var ajaxUrl = "{{url_for('views.swrPull')}}";
}
$.ajax({
data: ajaxData,
type: "POST",
url: ajaxUrl,
}).done(function (data) {
zipName.fileName = data.fileName;
zipName.filePath = data.output;
firstPass = primeDOM(
firstPass,
zipName.fileName,
zipName.filePath,
data.output
);
});
e.preventDefault();
});
$("#downloadIcon").click(function () {
console.log(zipName.fileName);
});
});
</script>
trends.html - this is the one that works w/ containers and such removed:
{% extends "index.html" %} {% block content %}
<form id="form" class="mt-4">
<textarea
type="text"
id="mistiId"
name="mistiIds"
placeholder="AE208"
required
class="form-control"
style="height: 93%; width: 100%"
></textarea>
<label for="mistiId">ID List (Seperate with comma):</label>
<input
type="text"
id="familyName"
name="familyName"
placeholder="XXX"
required
class="form-control"
/>
<label for="Family (Wildcard with '%')">
Device Family (Wildcard with '%'):</label>
<input
type="text"
id="logPoint"
name="logPoint"
placeholder="4800"
required
class="form-control"
/>
<label for="logPoint">LogPoint:</label>
<input
type="text"
id="opn"
name="opn"
placeholder="3600"
required
class="form-control"
/>
<label for="opn">Operation:</label>
<input
type="text"
id="daysBack"
name="daysBack"
placeholder="200"
required
class="form-control"
/>
<label for="daysBack">Days Back:</label>
<input
type="text"
id="daysStart"
name="daysStart"
placeholder="195"
required
class="form-control"
/>
<label for="daysStart">Start Day:</label>
<input
type="text"
id="folderName"
name="folderName"
placeholder="myFolderName"
required
class="form-control"
/>
<label for="folderName">Folder Name:</label>
<button type="submit" class="btn btn-primary mb-3">
</button>
</form>
{% endblock %}
splitAnalysis.html - this is the one that does not appear to return the data (or access the if statement) w/ containers and such removed:
{% extends "index.html" %} {% block content %}
<form id="formSWR" class="mt-4">
<input
type="text"
id="swrNo"
name="swrNo"
placeholder="SWR#"
required
class="form-control"
/>
<label for="swrNo"> SWR Numbers (seperate with comma):
</label>
<input
type="text"
id="fileLable"
name="fileLable"
placeholder="fileLable"
required
class="form-control"
/>
<label for="fileLable">
Label For File Names (use "_" instead of space):
</label>
<input
type="text"
id="folderName"
name="folderName"
placeholder="myFolderName"
required
class="form-control"
/>
<label for="folderName">Folder Name:</label>
<button type="submit" class="btn btn-primary mb-3">
</button>
</form>
{% endblock %}
I'm a little bit at a loss as to why one route seems to work fine and the other doesn't. I can see both have the correct string parameters when the respective forms are submitted, and I have added print("hey your in") to the swrPull() function after the if request.method == "POST" statement and nothing is logged in the console.
#views.route("/swrsplits", methods =["GET", "POST"])
def swrPull():
if request.method == "POST":
print("hey your in")
Thanks for any help!
Bit embarassing, but the issue was I had a typo in my logical operators:
if ((currForm = "form")) {
var ajaxData = {
_mistiList: $("#mistiId").val(),
_familyName: $("#familyName").val(),
_logPoint: $("#logPoint").val(),
_opn: $("#opn").val(),
_daysBack: $("#daysBack").val(),
_daysStart: $("#daysStart").val(),
_folderName: $("#folderName").val(),
};
var ajaxUrl = "{{url_for('views.trend')}}";
} else if ((currForm = "formSWR")) {
var ajaxData = {
_swrNo: $("#swrNo").val(),
_fileLable: $("#fileLable").val(),
_folderName: $("#folderName").val(),
};
Should be if ((currForm == "form")) {... and ...} else if ((currForm == "formSWR")) {...
Works as intended now

how to display plotly json object in html template

I have a django application that displays a few charts generated using plotly.
This is my views.py file
def home(request):
const_list = pd.read_csv('./const.csv').Const.unique()
party_list = pd.read_csv('./part_list.csv').abbr.unique()
all_list = pd.read_csv('./all_list.csv').All.unique()
chked=request.POST.get('chk', '')
print(chked)
if chked == 'true':
part_bargraph = main_graph(all_list, len(const_list))
else:
part_bargraph = main_graph(part_list, len(const_list))
context = {'main_graph': part_bargraph, 'const': const_list}
print(context)
return render(request, 'home.html', context)
The main_graph is a function that takes a list and an int value as parameters and generates a plotly graph. This graph is then returned as a json object using the plotly.io.to_json method.
I want to display this graph in an HTML template. This is what I am doing right now
<form method='post'>
{% csrf_token %}
<div class="switch">
<input id='chk' type="checkbox" class="switch-input" />
<label for="chk" class="switch-label">Switch</label>
</div>
</form>
<div class="main_graph" id='main_graph'></div>
<script>
Plotly.newPlot("main_graph", {{ main_graph | safe }})
$(document).on('click', '#chk', function (e) {
$.ajax({
type: 'POST',
url: '/home',
data: {
chk: $('#chk').prop('checked'),
csrfmiddlewaretoken: $('input[name=csrfmiddlewaretoken]').val()
},
success: function (data) {
Plotly.newPlot("main_graph", {{ main_graph | safe }})
}
});
})
</script>
When I print the context after toggling the button, I can see that the graph has changed. But I am not able to display that in the template.
What am I doing wrong?
Thanks in advance

Why the fields of card payment are empty?

I am creating an online shopping and the users should pay their orders by using a credit card payment. So, I created a sandbox account to test the Braintree API, install the Braintree and make the all configuration as it is shown the python files below. But, as you can notice in figure 3, the card information framework is displayed with only the card lables but there are the fields of the Card number, the Cvv and the expiration date of the card.
Payment/views.py:
import braintree
from django.shortcuts import render, redirect, get_object_or_404
from orders.models import Order
def payment_process(request):
order_id = request.session.get('order_id')
order = get_object_or_404(Order, id=order_id)
if request.method == 'POST':
# retrieve nonce
nonce = request.POST.get('payment_method_nonce', None)
# create and submit transaction
result = braintree.Transaction.sale({
'amount': '{:.2f}'.format(order.get_total_cost()),
'payment_method_nonce': nonce,
'options': {
'submit_for_settlement': True
}
})
if result.is_success:
# mark the order as paid
order.paid = True
# store the unique transaction id
order.braintree_id = result.transaction.id
order.save()
return redirect('payment:done')
else:
return redirect('payment:canceled')
else:
# generate token
client_token = braintree.ClientToken.generate()
return render(request,
'payment/process.html',
{'order': order,
'client_token': client_token})
def payment_done(request):
return render(request, 'payment/done.html')
def payment_canceled(request):
return render(request, 'payment/canceled.html')
After clicking on the Place order button, I was expecting to get a form like the one below but unfortunately, I've got a form without fields.
This is the template that displays the payment form and processes:
{% extends "base.html" %}
{% block title %}Pay by credit card{% endblock %}
{% block content %}
<h1>Pay by credit card</h1>
<form action="." id="payment" method="post">
<label for="card-number">Card Number</label>
<div id="card-number" class="field"></div>
<label for="cvv">CVV</label>
<div id="cvv" class="field"></div>
<label for="expiration-date">Expiration Date</label>
<div id="expiration-date" class="field"></div>
<input type="hidden" id="nonce" name="payment_method_nonce" value="">
{% csrf_token %}
<input type="submit" value="Pay">
</form>
<!-- Load the required client component. -->
<script src="https://js.braintreegateway.com/web/3.29.0/js/client.min.js">
</script>
<!-- Load Hosted Fields component. -->
<script src="https://js.braintreegateway.com/web/3.29.0/js/hostedfields.min.js"></script>
<script>
var form = document.querySelector('#payment');
var submit = document.querySelector('input[type="submit"]');
braintree.client.create({
authorization: '{{ client_token }}'
}, function (clientErr, clientInstance) {
if (clientErr) {
console.error(clientErr);
return;
}
braintree.hostedFields.create({
client: clientInstance,
styles: {
'input': {'font-size': '13px'},
'input.invalid': {'color': 'red'},
'input.valid': {'color': 'green'}
},
fields: {
number: {selector: '#card-number'},
cvv: {selector: '#cvv'},
expirationDate: {selector: '#expiration-date'}
}
}, function (hostedFieldsErr, hostedFieldsInstance) {
if (hostedFieldsErr) {
console.error(hostedFieldsErr);
return;
}
submit.removeAttribute('disabled');
form.addEventListener('submit', function (event) {
event.preventDefault();
hostedFieldsInstance.tokenize(function (tokenizeErr, payload) {
if (tokenizeErr) {
console.error(tokenizeErr);
return;
}
// set nonce to send to the server
document.getElementById('nonce').value = payload.nonce;
// submit form
document.getElementById('payment').submit();
});
}, false);
});
});
</script>
{% endblock %}
How can I get an "empty cart information" and not even have the cards fields while I have placed an order?
Thanks

how to update selected value of the dropdown list to the database

I got values of dropdown list which is expense.id and expense_type. In database I look for expense object which has id==expense.id sent by ajax in order to update its type (expense_type). So I need to send both expense.id and expense.type to sever using ajax. I dont know how to perform in jQuery as well as html. Below is my code I got error which is "Not Found: /polls/17/project_detail/ajax/update_form/"
<form action="/ajax/update_form/" method="POST" id="selection-form">
{% csrf_token %}
<select id="select_dropdown">
{% for expense in expenses %}
{% if project.id and expense.city %}
<option value="{{expense.id}}" selected="selected">{{expense.expense_type}}</option>
{% else %}
<option value="{{expense.id}}">{{expense.expense_type}}</option>
{% endif %}
{% endfor %}
</select>
<td><input type="submit" value="Save"></td>
</form>
=====js====
$('#selection-form').on('submit', function(event) {
event.preventDefault();
console.log("form_submitted");
create_post();
});
function create_post(){
console.log("update fucntion is working!");
var value = $("#select_dropdown").find(":selected").val();
var text = $("#select_dropdown option:selected").text();
$.ajax({
//url: "{% url 'update_form' %}",
url: "ajax/update_form/",
method: "POST",
data: {
"value": value,
"text": text,
//"pro_expense": pro_expense,
//"id": valueSelected,
csrfmiddlewaretoken: '{{ csrf_token }}',
},
//dataType: "json",
success: function(data){
console.log(data);
},
error: function(error_data){
console.log("error")
console.log(error_data)
}
});
return false;
};
====views.py=====
#csrf_exempt
def update_form(request):
if request.method == "POST" and request.is_ajax():
value = request.POST.get('value')
text = request.POST.get('text')
expense = Expense.objects.get(pk = value)
expense.expense_type = text
expense.save()
return HttpResponse({"result": "success"}, content_type="application/json")
===urls.py===
url(r'^(?P<project_id>[0-9]+)/project_detail/$', views.project_detail, name='project_detail'),
url(r'^ajax/update_form/$', views.update_form, name = 'update_form'),
error is "Not Found: /polls/17/project_detail/ajax/update_form/". please help. Any help will be highly appreciated!!

Facing problem in returning the ongoing upload status back to the HTML using AJAX in Django

I am trying to implement "Upload Progress Bar" in Django.
Following is my code in the template file:
{% extends "index_base.html" %}
{% block content %}
<script src="/media/js/functions.js" type="text/javascript"></script>
<script src="/media/js/jquery.js" type="text/javascript"> </script>
<script type="text/javascript">
var xhrObject1;
var xhrObject2;
function createXMLHttpObject()
{
var xhrObject; // The variable that makes Ajax possible!
try
{
xhrObject = new XMLHttpRequest();
}
catch (e)
{
try{
xhrObject = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e){
try {
xhrObject = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
xhrObject = null;
}
}
}
return xhrObject;
}
function ajaxFunction()
{
xhrObject1 = createXMLHttpObject();
if (xhrObject1 == null)
{
alert("Your browser does not support ajax.");
return;
}
xhrObject1.onreadystatechange = function(){
if(xhrObject1.readyState == 4){
document.getElementById("targetDiv").innerHTML = xhrObject1.responseText;
}
else
{
xhrObject2 = createXMLHttpObject();
xhrObject2.onreadystatechange = function(){
if(xhrObject2.readyState == 4){
document.getElementById("targetDiv").innerHTML = xhrObject2.responseText;
}
else
{
document.getElementById("targetDiv").innerHTML = "getting progress...";
}
}
xhrObject2.open("GET", "/upload_progress.psp", true);
xhrObject2.send(null);
}
}
var arrFiles = document.getElementById('id_file');
var fileToUpload = arrFiles.files[0];
xhrObject1.open("POST", "/upload.psp/", true);
xhrObject1.send(fileToUpload);
}
function submitForm()
{
document.forms["myform"].submit();
ajaxFunction();
return false;
}
</script>
<div id="main_container">
{% include "includes/nav.html" %}
<!------- Main Contents ---------->
<div id="contents_holder">
<div id="contents">
<div id="c_banner">
<span class="main_title">Upload File</span>
</div>
<div id="targetDiv" > </div>
<div id="setting">
<form name="myform" id="myform" action="/upload.psp/" method="post" enctype="multipart/form-data">
<h2>Upload File</h2></br>
<p>{{ form.file.label_tag }} {{ form.file }}</p></br>
<input type="button" value="Upload" name="uploadButton" onclick="javascript:return submitForm();"/>
<input type="button" value="Cancel" name="cancelUploadButton" onclick ="cancelUploadClicked()"/>
<input type="hidden" value="title" name="title" id="title" />
</form>
</div>
</div>
</div>
</div>
{% endblock %}
Following are my two functions inside views.py:
#condition(etag_func=None)
def upload(request):
if request.method == 'POST':
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
#handle_uploaded_file(request.FILES['file'])
f = request.FILES['file']
filename = "/host_lighttpd/var/www/htdocs/satellite/static/Data/" + f.name
destination = open(filename, 'wb+')
for chunk in f.chunks():
destination.write(chunk)
#yield chunk
request.session['uploaded'] += chunk
destination.close()
return render_to_response('uploadsuccess.html')
else:
form = UploadFileForm()
return render_to_response('upload.html', {'form': form})
def upload_progress(request):
#uploaded = request.session['uploaded']
return HttpResponse("Upload progress function...")
#return HttpResponse(uploaded)
My problem is how can I return the upload status back to the
second ajax call (GET method), so that it can be eventually updated
inside the html.
I don't know how can I return the ongoing uploading status.
Any help would be appreciated. Thanks in advance.
I recently had to do a bit of digging to find a solution for this myself.
Check out :-
http://fairviewcomputing.com/blog/2008/10/21/ajax-upload-progress-bars-jquery-django-nginx/
I have not tried the solution referenced yet, but it looks reasonable enough.
It involves registering a custom file upload class to expose the upload progress information.

Categories

Resources