Disable clicking on header elements of django-table2 - python

I am getting some data from DB and displaying it to the users using django-table2. My application need user to select any row and based on that I am loading a different page with data relevant to the row selected in the last page. To get this working I am using two hidden fields who's value will be set when I click on some row and that will be passed at the server side for further processing..
The problem I am facing is when i click on the rows it sets the hidden field with correct value but if i click on the header of the table everything gets messed-up. To allow post back on click of the table I have used {{render_table table_name}} in a form tag..
My tables.py
class testTable(tables.Table): // Have used orderable=False for all the rows
release_date = tables.Column(verbose_name="Release date",orderable=False)
product_name = tables.Column(verbose_name="Product name",orderable=False)
...
class Meta:
orderable = False
Views.py
table = productTable(dic)
table.paginate(page=request.GET.get('page', 1), per_page=5)
params['table'] =table
product.html
<div>
<form method="POST" name="form-product-list" action="{% url "product" %}" id="form-product-list" enctype="multipart/form-data">
<input type="hidden" name="prod_ver" value="0" id="prod_ver" />
<input type="hidden" name="release_date" value="0" id="release_date" />
{% render_table table %}
</form>
</div>
Javascript
function addRowHandlers() {
var table = document.getElementById("prod_details");
var rows = table.rows;
for (var i = 0; i < rows.length; i++) {
rows[i].onclick = (function() {
return function() {
$("#prod_ver").val(this.cells[1].innerHTML);
$("#release_date").val(this.cells[0].innerHTML);
};
})(i);
}
}
Currently when I click on any row I will get prod_ver = 1 and release_date = somedate but when I click on the header I am getting prod_ver = prod_ver and release_date =release_date..
Please look into this and ask if you need any clarification.

So it work, as it is supposed to. You should try to loop over table rows only inside "tbody".
in jquery it should look like this:
$("body").on("click","tableSelector >tbody >tr", function(){
$("#prod_ver").val($(this).children().eq(1));
$("#release_date").val($(this).children().eq(0));
});

Related

Read from two different forms in Flask

In my page I have two different forms. I want to read the information from the first form whenever I press a button in the second form. Is this possible?
First form:
<form id="loadData" method="post" action="/loadData">
{% if day %}
Day: <input id="day" name="day" size="5px" value={{day}}>
Month: <input id="month" name="month" size="5px" value={{month}}>
Year: <input id="year" name="year" size="5px" value={{year}}>
{% else %}
Day: <input id="day" name="day" size="5px">
Month: <input id="month" name="month" size="5px">
Year: <input id="year" name="year" size="5px">
{% endif %}
.
.
.
</form>
Second form:
<form id="createFile" method="post" action="/createFile">
<button type="submit">Create</button>
</form>
By clicking the button in the second form I want to read the information in the first one to create a file containing all those information.
I tried something like
#app.route("/createFile", methods=["GET", "POST"])
def createFile():
if request.method == "POST":
day = request.form["day"]
month = request.form["month"]
year = request.form["year"]
return redirect('/')
but I can't manage to read those variable properly.
Despite corresponding in the comments i'm not entirely sure this is your end goal, but let's give it a go?
basically all i did was copy stuff from the links attached in the comment.
a.html:
<form id="form_id" action="/loadData" method="POST">
<input type="text" name="q" value="abcd">
<button type="submit">loadData</button>
</form>
<button id="createFile"> createFile </button>
<script>
function post(path, params, method = 'post') {
// The rest of this code assumes you are not using a library.
// It can be made less verbose if you use one.
const form = document.createElement('form');
form.method = method;
form.action = path;
for (const key in params) {
if (params.hasOwnProperty(key)) {
const hiddenField = document.createElement('input');
hiddenField.type = 'hidden';
hiddenField.name = key;
hiddenField.value = params[key];
form.appendChild(hiddenField);
}
}
document.body.appendChild(form);
form.submit();
}
var form_1 = document.querySelector('#form_id')
document.querySelector('#createFile').addEventListener('click', (e) => {
var data = Object.fromEntries(new FormData(form_1).entries());
post("/createFile",data)
});
</script>
app.py:
from crypt import methods
from flask import Flask, request
app = Flask(__name__)
#app.route("/loadData", methods=["POST"])
def loadData():
data = request.get_data()
return f"<h1 style='color:blue'>loadData data: {data}</h1>"
#app.route("/createFile", methods=["POST"])
def createFile():
data = request.get_data()
return f"<h1 style='color:red'>createFile data: {data}</h1>"
if __name__ == "__main__":
app.run(host='0.0.0.0')
page looks like this:
clicking on loadData:
clicking on createFile:
this whole setup is pretty convoluted and unnecessarily complex. what are you trying to achieve?

How to pass value from HTML page to use in python on postgresql query command

First of all, I tried to get data from Postgresql, tried to show them into drop down list in HTML page, sent data from that drop down list which is selected one option to send back to python and use it to query data in Postgresql and finally showed the final result in HTML page again
I failed to list those list and send it back to python right now and I don't know much about Python, Jinja and Javascript.
This is my python code :
from flask import Flask, render_template, request
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
import operation
user = 'postgres'
pwd = '12345'
host = '127.0.0.1'
port = '5432'
dbname = 'test'
# engine = create_engine(f'postgresql://{user}:{pwd}#{host}:{port}/{dbname}',pool_size=100,
max_overflow=0)
engine = create_engine(f'postgresql://{user}:{pwd}#{host}:{port}/{dbname}')
db = scoped_session(sessionmaker(bind=engine))
app = Flask(__name__)
app.config["SESSION_PERMANENT"] = False
app.config["SESSION_TYPE"] = "filesystem"
#app.route('/testday', methods=["POST", "GET"])
def testday():
startday=request.form.get("startday")
endday=request.form.get("endday")
selectday=request.form.get("atday")
formulaselect = request.form.get("formula") <WANT THIS FROM HTML PAGE>
shiftvalue = request.form.get("shift") #WANT THIS FROM HTML PAGE
# Minimun day range in html date select
minday = db.execute('SELECT ("DATETIME"::timestamp::date) as "DATETIME" FROM "PL6_Daily" GROUP BY
date("DATETIME") ORDER BY date("DATETIME") ASC limit 1 ')
minday = minday.first()[0] #DONE
# print(minday)
# Maximum day range in html date select
maxday = db.execute('SELECT ("DATETIME"::timestamp::date) as "DATETIME" FROM "PL6_Daily" GROUP BY
date("DATETIME") ORDER BY date("DATETIME") DESC limit 1 ')
maxday = maxday.first()[0] #DONE
# print(maxday)
# List formula in drop down list
formula = db.execute('SELECT DISTINCT "FORMULA" FROM "PL6_Daily"').fetchall() #DONE
# List shift in drop down list
shift = db.execute('SELECT DISTINCT "SHIFT" FROM "PL6_Daily"').fetchall() #DONE
#Template use with data from html page, The one I want to resolve -->
performance = db.execute('SELECT DISTINCT "FORMULA","SHIFT", ("DATETIME"::timestamp::date) as
"DateTime", "PERFORMANCE" FROM "xxxx" WHERE ("DATETIME"::timestamp::date) = $$2020-01-03$$
<DONE> AND "FORMULA" = *data selected from html page* AND "SHIFT" = <data selected from html page>
GROUP BY "FORMULA", date("DATETIME"),"SHIFT","PERFORMANCE" ORDER BY date("DATETIME") ',
{"shiftvalue":shiftvalue, "formula":formula, "selectday":selectday})
db.commit()
# db.close()
print(formulaselect)
print(shiftvalue)
print(selectday)
return render_template("testday.html",maxday=maxday,minday=minday,formula=formula,shift=shift)
if __name__ == "__main__":
app.run(debug=True)
And this is my HTML page
{% extends 'base.html'%}
{% block title %}<title>TestDay</title>{% endblock title %}
{% block content %}
<div class="box">
<form action="{{ url_for('testday')}}" method="post">
<label for="formula">Select Formula :</label>
<select id="formulaselect" onchange="ddselect();">
{%for i in formula%}
<option value="{{i.FORMULA|e}}">{{i.FORMULA|e}}</option>
{% endfor %}
</select>
<input type="text" id="formulavalue"/>
<script>
function ddselect()
{
var d = document.getElementById("formulaselect");
var display = d.options[d.selectedIndex].text;
document.getElementById("formulavalue").value = display;
document.getElementById("formulavalue").value =
document.getElementById("formula").value;
}
</script>
<label for="atdat">Select Shift :</label>
<select id="shift" onchange="svselect();">
{% for s in shift %}
<option value="{{s['SHIFT']}}">{{s['SHIFT']}}</option>
{% endfor %}
</select>
<p id="shift"></p>
<input type="text" id="shiftvalue"/>
<script>
function svselect()
{
var d = document.getElementById("shift");
var display = d.options[d.selectedIndex].text;
document.getElementById("shiftvalue").value = display;
document.getElementById("shiftvalue").value = document.getElementById("shift").value;
}
</script>
<label for="atday">Select Date :</label>
<input type="date" id="atday" name="atday" value={{minday}} min={{minday}} max= {{maxday}}>
<input type="submit">
</form>
</div>
I made 2 drop down lists which are formula name and shift and successfully show them in the list but I stuck at sending one of value inside drop down list back to python to query new data from Postgresql. Those two boxes next to each drop down list are just for showing the value that I selected.
s1
s2
S3
This is some of my data from postgresql :
s4
and this is the result I want to show on HTML page (image from query in postgresql with acquired data):
s5
I'm sorry it's kinda messy since I'm really new to this.

Star Rating Bootstrap Data Input to Flask

After much help and many attempts at getting this functional I have now done so. The code below should be sufficient should anyone else also want to do the same.
Jinja2 Template
<div class="panel-footer">
<label for="input-2" class="control-label">My Rating:</label>
<input id="stars_{{result.id}}" name="input-2" class="rating rating-loading" data-min="0" data-max="10" data-step="0.1" data-stars="10" data-size="xs"onchange="updateStars('{{result.id}}')" >
</div>
<form action="{{url_for('delete_f', id=result.id)}}" method="post">
<input type="hidden" name="_method" value="DELETE">
<input type="submit" value="Delete" class="btn btn-danger">
</form>
</div>
JavaScript
{% for result in results %}
<script type="text/javascript">
function updateStars(id) {
var rating = document.getElementById("stars_" + id).value;
$.ajax({
url : '/rate_movie',
headers: {"Content-Type": "application/json"},
type : 'POST',
dataType: 'json',
data : JSON.stringify{'id': 'id', 'rating': rating}
});
};
</script>
{% endfor %}
Flask Backend
#app.route('/rate_movie',methods=['GET','POST'])
def rate_movie():
# Create cursor
if request.method == 'POST':
data = request.get_json(force=True)
rating = data['rating']
id = data['id']
cursor = cnx.cursor()
# Execute
#cursor.execute("UPDATE favourites SET rating=5 WHERE id =49") ## Works
cursor.execute("UPDATE favourites SET rating=%s WHERE id =%s",(rating,id))
#("INSERT INTO favourites(rating)VALUES(%s) WHERE id =%s" ,(rating,id))
# Commit to DB
cnx.commit()
#Close connection
cursor.close()
flash('Movie Rated', 'success')
return redirect(url_for('my_f'))
There are a number of problems here, but your first big issue is that you're using non-unique ids. Make your Ids unique and you can properly reference the value of your hidden input, fix your jQuery listener to look like $('#actually_uniqe_id').on('change', function (){...} instead of the mess it is currently, you can get your value correctly with var rating = document.getElementById("#actually_unique_id").value; and modify your posted data to convey both the id and rating like data: {'id': {{result.id}}, 'rating': rating}.
Never use non-unique IDs. Because of confusion surrounding this point, your current jQuery event listener is meaningless, and your rate_id variable is undefined because document.getElementById("{{result.id}}") fetches the first reference of that id, which is a div that has no attribute 'value'.
Edit: Also, since you have a loop generating potentially lots of rating inputs, drop the event listener for something like:
<input id="value_{{result.id}}" type="hidden" onchange="updateStars('{{result.id}}')" />
and
<script type="text/javascript">
function updateStars(id) {
var rating = document.getElementById("value_" + id).value;
$.ajax({
url : '/dashboard',
type : 'POST',
data : {'id': '{{result.id}}', 'rating': rating}
});
</script>

Django basic form - read a variable from views.py

I'm trying to implement a form of a single field in Django. The objective is to pass an integer variable (counter) to the views.py file. The template is completely custom, the value of the variable "counter" is shown in the screen while it can be increased/decreased using two buttons.
I can't manage to read this variable from my views.py file, and I have no idea what I am doing wrong. This is what I've done:
Template file:
<form method="POST" action="{% url 'animo' ejercicio=ejercicio %}">{% csrf_token %}
<p class="mensaje">{{pregunta_valoracion}}</p>
<div id="contadormin">
<input type="button" id="number-change-button" value="-" onclick="subtract()" name="counter"/>
<div id="minutos">
<p id="counter">0 {{unidad}}</p>
</div><script>
var i = 0;
var uni = {{unidad}};
function add() {
document.getElementById('counter').value = ++i;
document.getElementById('counter').innerHTML = i;
}
function subtract() {
if (i> 0){
document.getElementById('counter').value = --i;
document.getElementById('counter').innerHTML = i;
}
}
</script>
<input type="button" id="number-change-button" value="+" onclick="add()" name="counter" />
</div>
<input type="submit" class="save btn btn-default" value= "HECHO"</input>
</form>
Views file:
if request.method == 'POST':
veces = request.POST.get('counter', '')
Any ideas?
The only items with name="counter" in your template are the + and - buttons. You don't actually have a field containing the counter value itself, so there's no way it can be submitted in the form.
Remove the "counter" names from those buttons, and instead of putting the counter value in a <p> element, put it in an <input name="counter">.

Ajax succesfull call show div with form data

views.py
def index(request):
""""""""""""""
registerform = UserRegisterForm(request.POST)
createprofileform = UserCreateProfileForm(request.POST)
if registerform.is_valid() and createprofileform.is_valid():
result = registerform.save(commit=False)
result.set_password(request.POST['password']) #set member password
result.username = username
result.save()
member.user_id = user.id
member.member_id = result.id
member.save() #new member registration
member_profile = UserProfile.objects.get(user=result.id)
createprofileform = UserCreateProfileForm(request.POST, instance=member_profile)
createprofileform.save() #create member profile
createprofileform = UserCreateProfileForm()
member_save_msg = 'New member has been added.'
""""""""""""
return render(request,'index.html',{ 'registerform': registerform,'createprofile': createprofileform,})
index.html
{% block main-content %}
<table width="98%" border="0" style="margin-left:0.7%;" cellpadding="0" cellspacing="0" id="rounded_table">
<tr >
<td width="50%">Main Account Holder</td><td width="50%">Authorised Reporters</td>
</tr>
<tr id="main_account">
<td width="50%">All data related to main account holder comes here</td>
</tr>
<tr id="authorised_reporter">
<td width="100%" colspan="2">
<div id="authorisedreporter" {% if not registerform.errors %}style="display:none"{% endif %}>
<form method="post" action="." id="reporter-form">{% csrf_token %}
<table width="100%">
<tr>
<td style="width:100px;">First name:</td><td>{{registerform.first_name}}</td>
</tr>
<tr>
<td>Last name:</td><td>{{registerform.last_name}} </td>
</tr>
""""""other form fields""""""""
<tr>
<td colspan=2""><p align="right"><button type="submit" title="Save" >Save <img src="{{ STATIC_URL }}images/button-icon-ir-fwd.png" width="12" height="17" alt="" /></button></p>
</td>
</tr>
</table></form>
</table>
{%endblock%}
The above views.py and index.html is for saving the new user entry.
My html template is divided into 2 section,Main Account Holder tab and Authorised Reporters tab.Main Account Holder tab is for saving profile info and Authorised Reporters tab is for creating new user.on page load Main Account Holder tab will be active and user tab will be hidden.If user tab is selected,Main Account Holder tab will be hidden.Once the user is saved,the user details are displayed below, in below format.
{% for list in member_list %}
<tr class="ir-shade">
<td style="width:120px;"><span><input type="submit" name="delete" value="{{list.0.id}}" class="delete_reporter" /></span><button> id="{{ list.0.id }}" class="openDiv">{{list.0.first_name|title}} {{list.0.last_name}}</button></td>
<td style="width:410px;"> {{list.0.email}} {{list.1.phone_daytime}} {{list.1.phone_mobile}}</td>
</tr>
{% endfor %}
What i actually want is Onclicking the <button> id="{{ list.0.id }}" class="openDiv">{{list.0.first_name|title}} {{list.0.last_name}}</button> saved user data should shown in same field in editable mode.i am passing the user id in button.On click the button,the data related to user id should shown in editable mode.
js:
$('.openDiv').click(function () {
var id = $(this).attr('id');
var csrf_token = $("#csrf_token").val();
$.ajax({
data:{
csrfmiddlewaretoken: ('{{csrf_token}}'),
id:id,
},
type:'POST',
url: '/setting/save-reporter/',
success: function(data) {
$('#authorisedreporter').html(data);
}
});
});
The below views.py and html are written for showing the saved form instance.Now i can show the saved form instance and i am loading the instance into authorisedreporter div(please check in js and index.html).In this time if i kit save,it is creating new record,it is calling the views.py related to index method.I want to update and not save the record.
save_reporter.html
<form method="post" action="." id="{{ id }}">
{% csrf_token %}
<table width="100%">
<tr>
<td style="width:100px;">First name:</td><td>{{form.first_name}}</td>
</tr>
<tr>
<td>Last name:</td><td>{{form.last_name}}</td>
</tr>
<tr>
<td>Daytime phone:</td><td>{{profile.phone_daytime}}</td>
</tr>
<tr>
<td>Mobile phone:</td><td>{{profile.phone_mobile}}</td>
</tr>
<tr>
<td>Email:</td><td>{{form.email}}</td>
</tr>
<tr>
<td>Password</td><td>{{form.password}}</td>
</tr>
<tr>
<td colspan=2"<p align="right">{% include "buttons/save.html" %}</p></td>
</tr></table></form>
views.py
def save_reporter(request):
user = request.user
id = request.POST.get('id')
user = User.objects.get(pk =id)
userprofile = UserProfile.objects.get(user=user.id)
form = ReporterRegisterForm(instance=user)
profileform = ProfilecontactForm(instance=userprofile)
return render(request, 'setting/save_reporter.html',
{'form': form,
'id':id,
'profile':profileform
})
I had explained my current issue i am facing,please have help me in doing this.Thanks
Let me analyze your JS code a bit, since I can see several errors/mistakes there:
$('.openDiv').click(function (e) {
e.preventDefault();
// where is following data taken from? At the point you click the .openDiv link, the form doesn't have any data yet so all of them will be empty string ''
var csrf_token = $("#csrf_token").val();
var id = $(this).closest('td').attr('id');
var firstname = $("#"+id).find('#id_first_name').val();
var lastname = $("#"+id).find('#id_last_name').val();
var phonedaytime = $("#"+id).find('#id_phone_daytime').val();
var phonemobile = $("#"+id).find('#id_phone_mobile').val();
var email = $("#"+id).find('#id_email').val();
// do you use AJAX to get the form or use it to save the form?
$.ajax({
data: $(this).serialize(), // this is wrong, $(this) is the link object, not a form
type:'POST',
url: '/setting/save-reporter/',
success: function(data) {
$('#authorisedreporter').html(data);
$('#authorisedreporter').show();
}
});
});
Ok as far as I understand, after clicking the link, you are using AJAX to send request to Django view to fetch back the correct instantiated form. So you should:
First, simplify your JS code:
$('.openDiv').click(function (e) {
e.preventDefault();
var this_id = $(this).closest('td').attr('id'); // get the user ID, since that's all you need
console.log(this_id); // making sure that you get the right ID
$.ajax({
data: { id: this_id },
type: 'POST',
url: '/setting/fetch-reporter-form/',
success: function(data) {
$('#authorisedreporter').html(data);
$('#authorisedreporter').show();
}
});
});
Next, split your old view to several views to focus on what it needs to do (note: you can leave your index view as it is now):
def fetch_reporter_form(request):
''' Change your save_reporter view name to this view '''
registerform = UserRegisterForm()
if request.method == 'POST':
id = request.POST.get('id', None)
if id:
user = get_object_or_404(pk=user.id)
userprofile = UserProfile.objects.get(user=user)
registerform = UserRegisterForm(request.POST, instance=user)
return render(request, 'setting/register_form.html', {
'user_id': id
'registerform':registerform
})
else:
return HttpResponse('Request does not contain any ID')
else:
return HttpResponse('Request is not POST')
def update_reporter(request):
''' This function is for update the reporter '''
registerform = UserRegisterForm()
if request.method == 'POST':
id = request.POST.get('id', None)
if id:
user = get_object_or_404(pk=user.id)
userprofile = UserProfile.objects.get(user=user)
registerform = UserRegisterForm(request.POST, instance=user)
if registerform.is_valid():
result = registerform.save(commit=False)
# saving code here ...
return HttpResponse('Success')
else:
return HttpResponse('Request does not contain any ID')
else:
return HttpResponse('Request is not POST')
You can see here there are 2 functions: 1 for fetching the right form from AJAX, the other for saving the data via normal form submit. Of course you should make the urls.py accordingly, something like:
urlpatterns = patterns('',
# ... your code ...
url(r'^setting/fetch-reporter-form/$', 'yourapp.views.fetch_reporter_form'),
url(r'^setting/update-reporter/$', 'yourapp.views.update_reporter'),
)
You might also notice that you should make a new template setting/register_form.html that include your registration form HTML only (note: you need a hidden id field that was returned by fetch_reporter_form view above to identify the form):
<form method="post" action="/setting/update-reporter" id="reporter-form">
{% csrf_token %}
<input type="hidden" name="id" value="{{ user_id }}" />
<!-- your code here -->
</form>
So the flow is:
You go to index view. There is several forms to save new reporter, etc. as normal.
You click on the .openDiv button. It will send the AJAX request above to fetch_reporter_form to get the correct form. (Your code is working fine at this point)
You click Save button on that form, it will submit the updated data (via POST) to update_report view and update the reporter.
I'm just trying to give you the basic idea. The rest is quite straightforward so I guess you can continue easily. Hope it helps!
Let me resume what you are doing:
$.ajax({
data:{
/* ... */
},
type:'POST',
url: '/report/save_reporter/',
success: function() {
return true;
}
});
Here you setup an Ajax asynchronous query to post data to the server. When the query reaches the server, if it doesn't crash, the success: callback is called and javascript does nothing (return true;).
$('#authorisedreporter').show();
Here, you show an HTML node before the asynchronous Ajax query ends (succeeds or fails). To show the element after the Ajax query is done, put this code inside the success: or error: callback.
Finally, if you count your (, ), { and } you will see than $('#authorisedreporter').show(); is outside of the click callback. Therefore, if it is out of the document ready callback, it will have no effect.
So the right Javascript code should be (I think):
$('.openDiv').click(function (e) {
e.preventDefault();
var id = $(this).attr('id');
var firstname = $("#"+id).find('#id_first_name').val();
var phonemobile = $("#"+id).find('id_phone_mobile').val();
$.ajax({
data:{
csrfmiddlewaretoken: csrf_token,
edit_reporter:true,
id:id,
first_name:firstname,
phone_mobile:phonemobile,
},
type:'POST',
url: '/report/save_reporter/',
success: function() {
$('#authorisedreporter').show();
}
});
});
EDIT:
About your view.py, you save a UserProfile but do not return anything to the client browser. Nothing.
def save_reporter(request):
user=User.objects.get(user=user) # you should use django.shortcuts.get_object_or_404
userprofile = Userprofile.objects.get(user=user) # same comment
if request.method == 'POST':
registerform = UserRegisterForm(request.POST,instance=user)
createprofileform = UserCreateProfileForm(request.POST,instance=userprofile)
# you create 2 forms above, but don't use them. Is it normal ?!
# you should do loops "if registerform .valid(): ... else: ..." and use it. Same for the 2nd form
if 'edit_reporter' in request.POST:
first_name=request.POST.get('first_name') # can be None
phone_mobile = request.POST.get('phone_mobile') # can be None
user = User.objects.get(pk=user)
user.first_name = first_name
user.save() # put it inside a try/except statment
userprofile = UserProfile.objects.get(pk=user) # use get_or_404
userprofile.phone_mobile = phone_mobile
userprofile.save() # put it inside a try/except statment
return HttpResponse() # this returns an empty html page, do you want to return the form here ?
Check if there is any error message returned from the server:
$.ajax({
// ...
error: function(err) {
console.log(err);
}
});
Edit:
You don't pass the user id when you submit the form. Try doing something like:
<form ...>
<!-- //.. -->
{{ form.id.as_hidden }}
</form>

Categories