I'm making a website using flask.
It displays a list using sql in top.html in which each element is a hypertext.
<table class="table table-striped">
<thead></thead>
<tr>
<th>Company</th>
</tr></thead>
<tbody>
{% for company in companies %}
<tr>
<td>{{ company.name }}</td>
</tr>
{% endfor %}
</tbody>
</table>
So i want to know which hypertext is clicked from the list so that i could load its respective content in /text.
please provide the python code also(flask code).
First put company unique identifier to each <a for example <a data-id="11" ...
Then add event listeners on each <a like this...
var companyLinks = document.querySelectorAll('.table-striped a');
for (var i = 0; i < companyLinks.length; i += 1) {
companyLinks[i].addEventListener('click', function (e) {
// get the company id of clicked link
var companyId = e.target.dataset.id;
// now do what you like with the company id
// for example you can send an AJAX call to your backend
});
}
Related
I am building a web app using Django. I am not that familiar with javascript/html since it is not my domain of specialty.
What I am doing is searching for a name that will be looked up in the api and it will return it with other information.
I'll post the codes which I think is realted to my issue. If you need anything more, I can provide it.
views.py
from django.shortcuts import render
from .models import customer
import requests
def get_customer(request):
all_customers = {}
if 'name' in request.GET:
name = request.GET['name']
url = 'https://retoolapi.dev/aSIZJV/customer__data?FirstName=%s'%name
response = requests.get(url)
data = response.json()
customers = data
for i in customers:
customer_data = customer(
uid = i['id'],
f_name = i['FirstName'],
m_name = i['MiddleName'],
l_name = i['LastName'],
phone = i['Phone'],
email = i['Email'],
DOB=i['DateOfBirth'],
EID=i['EmiratesID']
)
customer_data.save()
all_customers = customer.objects.all().order_by('-id')
return render (request, 'customer.html', { "all_customers": all_customers} )
customer.html
{% extends 'base.html'%}
{% load static %}
{% block content %}
<div class = "container">
<div class = "text-center container">
<br>
<h2 class = "text-center">Search for the desired customer</h2>
<br>
<form method="GET">
<input type='button' value='Remove Table Body' onclick='removeTableBody()'/>
<!-- I am trying to remove the table body using the line above, but it is not working-->
<input type = "text" name = "name" placeholder="Search..." class = "text-center">
<button type = "submit" class = "btn-danger btn-sm">SEARCH CUSTOMER</button>
</form>
</div>
<br><br>
<div class="container">
<h1>Customer Table</h1>
<div id="toolbar">
<select class="form-control">
<option value="">Export Basic</option>
<option value="all">Export All</option>
<option value="selected">Export Selected</option>
</select>
</div>
<table id="table"
data-toggle="table"
data-search="true"
data-filter-control="true"
data-show-export="true"
data-click-to-select="true"
data-toolbar="#toolbar">
<thead>
<tr>
<th data-field="state" data-checkbox="true"></th>
<th data-field="ID">ID</th>
<th data-field="FirstName" data-filter-control="input" data-sortable="true">First Name</th>
<th data-field="MiddleName" data-filter-control="input" data-sortable="true">Middle Name</th>
<th data-field="LastName" data-filter-control="input" data-sortable="true">Last Name</th>
<th data-field="Phone" data-filter-control="select" data-sortable="true">Phone</th>
<th data-field="Email" data-filter-control="select" data-sortable="true">Email</th>
<th data-field="DateOfBirth" data-filter-control="select" data-sortable="true">Date Of Birth</th>
<th data-field="EmiratesID" data-filter-control="select" data-sortable="true">EmiratesID</th>
</tr>
</thead>
<tbody>
{% for customer in all_customers %}
<tr>
<td class="bs-checkbox "><input data-index="0" name="btSelectItem" type="checkbox"></td>
<td>{{customer.uid}}</td>
<td>{{customer.f_name}}</td>
<td>{{customer.m_name}}</td>
<td>{{customer.l_name}}</td>
<td>{{customer.phone}}</td>
<td>{{customer.email}}</td>
<td>{{customer.DOB}}</td>
<td>{{customer.EID}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endblock %}
<!-- partial -->
static/website/dist/script.js
var $table = $('#table');
$(function () {
$('#toolbar').find('select').change(function () {
$table.bootstrapTable('refreshOptions', {
exportDataType: $(this).val()
});
});
})
var trBoldBlue = $("table");
$(trBoldBlue).on("click", "tr", function (){
$(this).toggleClass("bold-blue");
});
var $table_empty = $('#table');
$(function removeTableBody() {
$('#table tbody').empty();
})
// I wrote the line above to empty the table
When I press the button to empty the rows in the table, I see this on the terminal:
[15/Dec/2021 15:34:05] "GET /style.css HTTP/1.1" 404 2283
[15/Dec/2021 15:34:05] "GET /script.js HTTP/1.1" 404 2283
This a view of how the table looks:
enter image description here
I want to get new responses everytime I send a GET request.
Judging by the fact that your .css and your .js are reporting 404 not found, I'm going to assume that it's an issue with your static root. I think by default the STATIC_ROOT in your settings file will be /static, but your js is apparently at /static/web/dist, so you should either update your STATIC_ROOT to /static/web/dist or specify the path from /static in your base.html when you're loading the files.
(Edit)
Also. Your View is requesting data from another website and saving all the data it receives as new model instances. You're getting duplicates on your page because you have duplicates in your database, not because of the javascript.
Your javascript is set up to reload the page every time you hit Search Customer, so, the javascript failing to clear the table is definitely irrelevant to your duplicate problem.
Lastly, your removeTableBody function is inside $( ) which means the function only exists inside the scope of those brackets. So if you click your clear table button, I'm sure it would post to your console that the removeTableBody function doesn't exist. Remove the $( ).
I've got a large template file here that I'm accessing in a for loop to print a table with some values in it. When a user clicks on one of those values I'd like it to carry over just that 1 json block to another page in order to have it prefill some fields. I'm having trouble getting my program to select that single entry in the json dict in order to render the next page. Here's the code involved:
views.py
#apps.route('/add')
#login_required
#admin_required
def view_apps():
""" View available apps """
template = Template.query.all()
dir_path = os.path.dirname(os.path.realpath(__file__))
json_content = combine_json_templates()
print(json_content)
print(len(json_content))
return render_template('apps/add_app.html', apps=json_content)
def combine_json_templates():
master_list = []
cwd = os.getcwd()
print(cwd)
json_storage = 'app/storage/templates/json/'
for file in os.listdir(json_storage):
with open(json_storage + file) as json_path:
json_content = json.load(json_path)
for item in json_content:
master_list.append(item)
return master_list
#apps.route('/add/<int:app_id>')
#apps.route('/add/<int:app_id>/info')
def app_info(app_id):
app = json_content[""+app_id+""]
print(app)
add_app.html (code that displays the table and contains the onclick:
<div style="overflow-x: scroll;">
<table class="ui searchable sortable unstackable selectable celled table">
<thead>
<tr onclick="window.location.href = '{{ url_for('apps.app_info', app_id=apps.pop(['name'])) }}';">
<th class="sorted ascending">Title</th>
<th>Desctiption</th>
<th>Catagory</th>
<th>Platform</th>
</tr>
</thead>
<tbody>
{% for a in apps | sort(attribute='title') %}
<tr>
<td>{{ a.title }}</td>
<td>{{ a.description }}</td>
<td>{{ a.categories }}</td>
<td>{{ a.platform }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
The part that I'm having trouble with is getting a unique value in order to pass it onto the next page and reference the correct json.
<tr onclick="window.location.href = '{{ url_for('apps.app_info', app_id=apps.pop(['name'])) }}';">
Should I be using a different method for referencing the json file? Should I be modifying it when loading the json files in order to add some kind of key?
This is my first flask project so I'm not sure the best way to go about this.
I think I have an approach, the question is whether you like it.
# ./__init__.py
def create_app():
app = Flask(__name__,
# default: ./var/app-instance/
instance_relative_config=True,
)
app.config.from_mapping(
SECRET_KEY=b'change-me\n',
)
try:
os.makedirs(app.instance_path)
except OSError:
pass
# init endpoints/blueprints here
from .apps import create_module as apps_create_module
apps_create_module(app)
return app
# ./app/apps/view.py
# TODO: move this to the apps configuration file
JSON_TEMPLATES_DIR = 'storage/templates/json'
def load_json_data(path):
data = []
for fname in glob(os.path.join(path, '*.json')):
with open(fname) as fp:
dataset = json.load(fp)
data.extend(dataset)
return data
#apps.route('/add')
#login_required
#admin_required
def list_apps():
'''View available apps'''
apps = load_json_data(
os.path.join(current_app.instance_path,
JSON_TEMPLATES_DIR))
return render_template('apps/add_app.html', **locals())
#apps.route('/add/info', methods=['POST'])
#csrf.exempt
def app_info():
'''View selected app'''
ident = request.form.get('ident', None)
if ident:
try:
app = json.loads(ident)
print(app)
except: pass
return render_template('apps/app_info.html', **locals())
<!-- "./app/templates/apps/add_app.html" -->
<div style="overflow-x: scroll;">
<table class="ui searchable sortable unstackable selectable celled table">
<thead>
<tr>
<th class="sorted ascending">Title</th>
<th>Description</th>
<th>Catagory</th>
<th>Platform</th>
</tr>
</thead>
<tbody>
{% for a in apps | sort(attribute='title') %}
<tr id="app-entry-{{loop.index}}">
<td>
<div class="namecell">
<span class="nametext" style="display: block;">{{ a.title }}</span>
<span class="btn-group" role="group" style="margin-top: 1rem">
<form method="post" action="{{url_for('apps.app_info')}}">
<input type="hidden" name="ident" value='{{app | tojson | safe}}' />
<button type="submit">Setup</button>
</form>
</span>
</div>
</td>
<td>{{ a.description }}</td>
<td>{{ a.categories }}</td>
<td>{{ a.platform }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
new to coding. I'm creating an inventory table'with the django framework. I'd like to be able to click on a table row (which is a part) that will then parse that row/part information to a detail view. from what I understand table rows are inline elements and inline elements are psuedo code which current HTML does not allow for an anchor tag to be thrown in (bad practice?) so I need to use some javascript. Currently, the inventory view shows when I use runserver (http://127.0.0.1:8000/inventory/) but clicking on any row does nothing. Here is what I have so far;
inventory.html
{% extends "base.html" %}
{% block body %}
<br>
<table class="table table-hover">
<thead>
<tr>
<th>Part Number</th>
<th>Description</th>
<th>Location</th>
<th>Supplier</th>
<th>S.O.H</th>
</tr>
</thead>
<tbody>
{% for part in parts %}
<!-- need to make these table rows link to their respective parts
class="table_row" href="{{ selected_part.partnumber }}/detail">{{ selected_part.partnumber }}-->
<tr data-href="{% url 'detail' part.pk %}">
<td>{{ part.pk }}</td>
<td>{{ part.partnumber }}</td>
<td>{{ part.description }}</td>
<td>{{ part.location }}</td>
<td>{{ part.supplier }}</td>
<td>{{ part.stockonhand }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
urls.py
from django.urls import path
from .views import *
urlpatterns = [
path('inventory/', inventory_list, name='inventory'), # URL path for inventory_list view
path('<str:pk>/', part_information, name='detail'),
path('', index, name='index'),
]
custom.js
$('tr[data-href]').on("click", function() {
document.location = $(this).data('href');
});
base.html has <script src="/docs/4.4/dist/js/custom.js"></script> before the </body> tag.
I think the issues is in my javascript file. I'm pretty new to this and simplified explanations would be greatly appreciated
Use the below in your custom.js file. When the page is loaded then this function $(document).ready() gets executed initialising the tr on what to do 'On Click'
$(document).ready(function(){
$('table tr').click(function(){
window.location = $(this).data('href');
return false;
});
});
I'm having a hell of a time here trying to get this to work. I'm pretty sure I've done almost all the research I can trying to solve this, and I just can't figure out where I'm going wrong. So, that being said, thanks in advance for any help you guys can offer.
I'll start by posting my code:
HTML:
{% block main %}
<form action="{{ url_for('index') }}" method="post">
<fieldset>
<div id ="total" class="form-inline">
<div id="itemBackground" class="col-sm-6">
<div id="itemToolBar" class="row">
<div class="col-sm-6">
<label>
Show:
<select name="list_length" class="form-control input-sm">
<option value="10">10</option>
<option value="25">25</option>
<option value="50">50</option>
<option value="100">100</option>
</select>
</label>
</div>
<div class="col-sm-6" align="right">
<label>
Search:
<input class="form-control input-sm" autocomplete="off" type="textbox" name="q" id="q" placeholder="">
</label>
</div>
</div>
<table id="itemTable" name="itemTable" class="table table-hover table-inverse">
<thead>
<tr id="head">
<th>ID</th>
<th>Item</th>
<th>Buy</th>
<th>Sell</th>
</tr>
</thead>
{% for item in items %}
<tr id="rows">
<td scope="row">{{ item[0] }}</td>
<td>{{ item[1] }}</td>
<td>{{ item[2] }}</td>
<td>{{ item[3] }}</td>
</tr>
{% endfor %}
</table>
</div>
<div id = "vehicleBackground" class="col-sm-6">
<table id="vehicleTable" class="table table-hover table-inverse">
<thead>
<tr id="head">
<th>ID</th>
<th>Item</th>
<th>Buy</th>
</tr>
</thead>
{% for vehicle in vehicles %}
<tr id="rows">
<th scope="row">{{ vehicle[0] }}</th>
<td>{{ vehicle[1] }}</td>
<td>{{ vehicle[2] }}</td>
</tr>
{% endfor %}
</table>
</div>
</div>
</fieldset>
</form>
{% endblock %}
Python:
# configure application
app = Flask(__name__)
# ensure responses aren't cached
if app.config["DEBUG"]:
#app.after_request
def after_request(response):
response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
response.headers["Expires"] = 0
response.headers["Pragma"] = "no-cache"
return response
# configure session to use filesystem (instead of signed cookies)
app.config["SESSION_FILE_DIR"] = gettempdir()
app.config["SESSION_PERMANENT"] = False
app.config["SESSION_TYPE"] = "filesystem"
Session(app)
#app.route("/", methods=["GET", "POST"])
def index():
if request.method == "POST":
if not request.form.get("q"):
return print("Give me a search query")
else:
q = request.form.get("q") + "%"
print(q)
conn = sqlite3.connect('items.db')
db = conn.cursor()
db.execute("SELECT * FROM items WHERE item LIKE '{}'".format(q))
itemList = db.fetchall()
db.execute("SELECT * FROM vehicles")
vehicleList = db.fetchall()
db.close()
conn.close()
return render_template("index.html", items = itemList, vehicles = vehicleList)
# else if user reached route via GET (as by clicking a link or via redirect)
else:
# configure CS50 Library to use SQLite database
conn = sqlite3.connect('items.db')
db = conn.cursor()
db.execute("SELECT * FROM items")
itemList = db.fetchall()
db.execute("SELECT * FROM vehicles")
vehicleList = db.fetchall()
db.close()
conn.close()
return render_template("index.html", items = itemList, vehicles = vehicleList)
#app.route("/search")
def search():
"""Search for places that match query."""
print("here")
# TODO
q = request.args.get("q") + "%"
items = db.execute("SELECT * FROM items WHERE item LIKE '{}'".format(q))
return jsonify(items)
Javascript:
// execute when the DOM is fully loaded
$( document ).ready(function() {
configure();
});
/**
* Configures application.
*/
function configure()
{
// configure typeahead
$("#q").on('input propertychange paste', function() {
//$("#q").val("hi");
// get items matching query (asynchronously)
var table = "<thead><tr><th>ID</th><th>Item</th><th>Buy</th><th>Sell</th></tr></thead><tr>";
var parameters = {
q: $("q").val()
};
$.getJSON(Flask.url_for("search"), parameters)
.done(function(data) {
$('#q').val("hi");
for (var i=0; i<data.length; i++) {
obj = data[i];
for (var key in obj) {
table += "<td>" + key + "</td>";
}
}
table += "</tr>";
$("#itemTable").replaceWith(table);
//document.getElementById('').innerHTML = table;
})
.fail(function() {
// log error to browser's console
console.log(errorThrown.toString());
});
});
// give focus to text box
$("#q").focus();
}
Where I'm stuck is with the javascript when I check for the textbox input to be changed and thus try to update the table with data that matches the query from my database. I do actually make it into the "input propertychange paste" section, I know because I set it to change the textbox value to "hi" whenever anything is typed in the box, but I never make it through the next section where I try to getJson from my /search python function, then format it into a table, and then replace the old table with the one I just made.
I'm not really sure what more information I can give you guys, but I'm sure I'm missing some stuff you need. So let me know if you do. Thanks again in advance for helping me out if you can!
Edit:
I should add that my code never even reaches into that getJSON block. As you can see I try to change the value of the input textbox inside of the getJSON call, but the textbox never gets updated to say "hi". Seems like I'm possible calling getJSON wrong? Not sure.
Edit2:
Okay, so I did manage to get into the getJSON call now. Thank you for your help with that. But now I'm onto the real part of my question, how would I go about formatting the table after I get the JSON from the SQL database? From what I can tell, I have the formatting at least mostly correct, but I might be having an issue when it comes to removing the old table and inserting the new one.
The selector #itemTable is not matched in HTML. The <table> element name attribute value is "itemTable"; the element does not have an id set at HTML. Use $("table[name=itemTable]") or set the id to "itemTable" at HTML to be able to use #itemTable selector and match the existing <table> element.
I created a table in Laravel with pagination and then added search functionality to it however when I try and search it only searches the current page. How would I fix this so that I can search the information that is on all the pages of the table? I am new to Laravel :)
Table code -
<input type="text" id="search" placeholder="Type to search">
<table id="table">
<thead>
<tr>
<th data-field="id">Ident</th>
<th data-field="name">Name</th>
</tr>
</thead>
<tbody>
#foreach ($airports as $airport)
<tr>
<td>{{ $airport->ident }}</td>
<td>{{ $airport->name }}</td>
</tr>
#endforeach
</tbody>
</table>
#include('pagination.default', ['paginator' => $airports])
Javascript -
<script type="text/javascript">
var $rows = $('#table tr');
$('#search').keyup(function() {
var val = $.trim($(this).val()).replace(/ +/g, ' ').toLowerCase();
$rows.show().filter(function() {
var text = $(this).text().replace(/\s+/g, ' ').toLowerCase();
return !~text.indexOf(val);
}).hide();
});
</script>
In laravel if you use pagination it will only load those specific records set in limit.
->paginate(15)
When you click the next page button at that time only new set of records will be loaded.So only you search is working for first page alone.
If you want this to work out you can make a ajax call to the controller where the page is loading like this
use App/Airport;
public function getAirportList(Request $request,Airport $airport){
if ($request->ajax()) {
$getResult = $airport->where(function($query){
$query->where('ident',$request->search)
->orWhere('name',$request->search);
});
return view('airports', compact('airports'));
}
$airports = $airport->paginate(10);
return view('airports',compact('airports'));
}