django passing arguments from template to bash script - python

I am trying to have an input field in the template that the user enters a query and that query goes to the views.py
and from there i m taking the query and pass it as argument to the bash script.
This is what i have for now.
views.py
def home(request):
if request.method == 'POST':
try:
query = request.POST['query']
test = subprocess.check_call(['home/.../bash.sh',
query])
return render(request, 'base.html', {'input': test})
except KeyError:
return HttpResponse("Nothing was submitted!")
base.html
<form action="/" method="post">
{% csrf_token %}
<input type="hidden" name="query" value="{{ input }}">
<input type="submit" value="Submit">
</form>
I am stuck right here..i don't know if i shout request.POST or something else much simpler...cause i don't want to use a form.

I figure it out by creating a script in the html template.
<script>
$(".opener").click(function () {
var thead = $("#mytable").find("thead");
thead.find('th').last().remove();
thead = thead.html();
var row = $(this).parents('tr');
row.find('td').last().remove();
row = row.html();
var table = $(document.createElement('table'));
table.append('<thead>' + thead + '</thead>');
table.append('<tbody><tr>' + row + '</tr></tbody>')
$(".modal").html("").append(table);
$(".modal").dialog({width: 'auto', position: 'top'});
});
</script>

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?

Sending submit data into Flask without page refresh

Intro:
I'm making an app with many records that allows you to have a ranking/upvote system
Pic attached:
The problem: I face is that each time I press 'Upvote +1', the page gets refreshed - and I want to solve it.
Here is my Flask app:
def form():
form = LoginForm()
value = 0
records = Row.query.order_by(Row.id.desc())
if form.validate_on_submit(): #if we submit something -> pick the ID of the item
for i in dict(request.form):
id_of_record_to_change = i
item = Row.query.filter_by(id=id_of_record_to_change) #filter item by the ID
new_value = item.first().rating + 1 #add +1 to the rating value
item.first().rating = new_value
db.session.commit() #record to database
return render_template('form.html', records=records, form=form, value=value)
Here is my html:
{{form.csrf_token }}
{% for item in records %}
{{ item.rating }}
<input type="hidden" id="intval" name="intval" value="{{ item.rating }}"> <!-- rating we want to increase -->
<input type="hidden" id="id" name="id" value="{{ item.id }}"> <!-- ID we want to pass -->
<input type="submit" id="target" name = "{{ item.id }}" value="Upvote +1"> <!-- submit action -->
{% endfor %}
</form>
Thank you!
I managed to solve my problem thanks to #RaniSharim who posted a link to the proper tutorial
Here is how my code changed:
In Flask app I added the following route to 'get/send/process' the data:
######## Data fetch ############
#app.route('/getdata/<index_no>', methods=['GET','POST'])
def data_get(index_no):
if request.method == 'GET': # POST request
item = Row.query.filter_by(id=index_no) #filter item by the ID
new_value = item.first().rating + 1 #add +1 to the rating value
item.first().rating = new_value
db.session.commit() #record to database
return '%s'%(new_value)
#################################
And my html file now looks like this:
{% for item in records %}
<hr>
<button id ="{{item.id}}" onclick="SomeFunc()">👍 {{ item.rating }}</button>
<!--- ################################ -->
<script >
function SomeFunc() {
var button = event.target;
var element_id = button.id;
index = element_id
fetch(`/getdata/${index}`)
.then(function(response) {
return response.text();
}).then(function(text) {
document.getElementById(index).innerText = '👍 ' + text;
});
} </script>
<!--- ################################ -->
{% endfor %}
In this way we can avoid page reload + we imitate the ranking change with JS
Thanks!

How to load content into div element with flask

I'd like to fill / update a div area in index.html with the result from the python function, but I don't know how to do this. I know there are several other questions with a similar topic but I couldn't succeed with them because they were too specific. I'm pulling my hair out over this.
Would be someone so nice and guide me?
This is a function in main.py:
#app.route('/')
def index():
return render_template('index.html')
#app.route('/stat/')
def stat():
a = 2
b = 10
return(str(a) + ' is not ' + str(b))
this is the index.html:
<body>
<form action="/stat/">
<button type="submit" id="btn1" class="btn btn-primary btn-sm">check stat</button>
</form>
<div id="stat_content"></div>
</body>
As #S3DEV points out, you will need to pass the string to the template via an additional argument. For example, we might do something like this:
#app.route('/stat/', methods=['GET', 'POST']) # EDIT
def stat():
a = 2
b = 10
text = f"{a} is not equal to {b}"
return render_template("index.html", text=text)
In the code above, we set text to be the string to be passed to the template. In the template, we will be able to access this string variable as text.
Now when index.html is rendered, it will be looking for the text variable that is passed in from the Flask application. This is taken care of by Jinja 2, which is the rendering engine used by Flask.
<div id="stat_content">
{% if text %}
<h2>No text to show</h2>
{% else %}
<h2>{{ text }}</h2>
{% endif %}
</div>
Using Jinja 2 syntax with curly braces, we first check if the text variable exists or not; if it does not exist, we render the message, "No text to show." This will happen when we first route into "/", or the default home route of the Flask app.
Once the user fills out the form, however, they will be redirected to "/stat/", at which point we will now have generated text and passed it back to index.html via the render_template("index.html", text=text) function call. Then, when Jinja 2 renders index.html, it will see that text was passed over from the Flask app and display that message, namely that 2 is not equal to 10.
You want this initiated from the button right? Here's how to achieve that with ajax...
<body>
<form action="/stat/">
<button type="submit" onclick="GetData();" id="btn1" class="btn btn-primary btn-sm">check stat</button>
</form>
<div id="stat_content"></div>
</body>
<script type="text/javascript">
function GetData() {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == XMLHttpRequest.DONE) { // XMLHttpRequest.DONE == 4
if (xmlhttp.status == 200) {
document.getElementById("stat_content").innerHTML = xmlhttp.responseText;
}
else if (xmlhttp.status == 400) {
alert('There was an error 400');
}
else {
alert('something else other than 200 was returned');
}
}
};
xmlhttp.open("GET", "/stat/", true);
xmlhttp.send();
}
</script>
to update the content of that div, i think (based on your logic) you need to perform an ajax call to your stat function with the two parameters a and b submitted via POST request:
<form class="form-stat needs-validation" novalidate role="form">
<div class="form-group">
<input type="text" class="form-control" name="a" value="">
<div class="invalid-feedback"></div>
</div>
<div class="form-group">
<input type="text" class="form-control" name="b" value="">
<div class="invalid-feedback"></div>
</div>
<button type="submit" id="btn1" class="btn btn-primary btn-sm">check stat</button>
</form>
<div id="stat_content">Output: ?</div>
put the javascript code below after jquery call
<script>
$(document).ready(function() {
"use strict";
$('.form-stat').submit(function(e) {
e.preventDefault();
$.ajax({
url: "{{ url_for('stat') }}",
type: 'POST',
cache: false,
dataType: 'json',
data: $('.form-stat').serialize(),
success: function(data) {
// console.log(data);
$('.form-stat input[name=a]').val(''); // reset field
$('.form-stat input[name=b]').val(''); // reset field
$('#stat_content').html(data); // update div with the returned vlue
}
});
});
});
</script>
and you have to make little change to your stat function so you can submit dynamically the two parameters via POST like so :
from flask import Flask, request, make_response
import json
#app.route('/stat', methods=['POST'])
def stat():
if request.method == 'POST':
a = request.form['a']
b = request.form['b']
# check if inputs are valid to work with ..
res = str(a) + ' is not ' + str(b) if a != b else str(a) + ' and ' + str(b) + ' are equal.'
resp = make_response(json.dumps(res))
resp.status_code = 200
return resp

Passing value and ID from Request.POST

I am trying to have a website with multiple input type ="text" fields which as a default have values from database in them.
Goal is to have X input types where X=number of entries in database and one extra input type box to add a new entry.
The problem is that if user edits a textfield and hits submit, Request.POST['event'] returns only the new value, not the id of the box that has been edited,
This is my current code:
<form method="post">
{% csrf_token %}
{% for choice in event %}
<form method ='POST'> {% csrf_token%}
<input type="text" name = "event" id="event{{ forloop.counter }}" value="{{choice.txt}}"><br>
<input type = 'submit' value = 'Zapisz'/>
</form>
{% endfor %}
<form method ='POST'> {% csrf_token%}
{{form.as_p}}<br>
<input type = 'submit' value = 'Zapisz'/>
</form>
and views.py:
def rpg_create(request):
try:
event = get_list_or_404(Event)
except:
event = ""
if request.method == 'POST':
try:
Adjusted_event = request.POST['event']
print (Adjusted_event)
except:
pass
form = RpgForm(request.POST or None)
if form.is_valid():
print(form)
form.save()
context = {
'form': form,
'event': event
}
return redirect('/rpgmaker', context)
else:
form = RpgForm()
context = {
'form': form,
'event': event
}
return render(request,"rpgmaker/rpg.html",context)

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">.

Categories