I have a flask dropzone to upload files.
Once an upload is done I want to print a log text on the html site
It works so far, the only problem is - the div tag doesn't update the log text after the second upload. The website stays with the text from the first upload.
index.html:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<script>
$(function(){
window.setInterval(function() {
loadNewLogger()
}, 500)
function loadNewLogger(){
$.ajax({
url:"/write_log",
type: "POST",
datatype: "json",
success: function(data){
$(logger).replaceWith(data)
}
});
}
});
</script>
<body>
<div style="color:rgb(0, 0, 0);text-align:center">
CDR PIPELINE </div>
{{ dropzone.create(action='upload') }}
{{ dropzone.load_js() }}
{{ dropzone.config() }}
<div id="logger">
{{ logger }}
</div>
</body>
</html>
logger.html (otherwise I would render index.html twice)
<div id="logger">
{{ logger }}
</div>
excerpt from flask_app.py:
#app.route('/',methods=['POST','GET'])
def upload():
if request.method == 'POST':
f = request.files.get('file')
f.save(os.path.join(app.config['UPLOADED_PATH'],f.filename))
upload.logger = ""
es.main()
upload.logger = es.main.result
return upload.logger
return render_template('index.html')
#app.route('/write_log',methods=['POST'])
def log():
logger = upload.logger
return jsonify('', render_template('logger.html', logger=logger))
Why is it updating the text from upload.logger only once?
First of all, instead of JQuery AJAX, I would recommend using PHP. For example, when you upload files from index.html you can redirect to upload.php, and you can display the message using "echo"
But even if you aren't comfortable with that, don't get too much into Python or JQuery. Your problem can very easily be solved with plain JavaScript:
Here is your html element in logger.html:
<div id="logger"></div>
In flask app.py:
document.getElementById("logger").innerHTML="Your message to be displayed"
I would also recommend you to remove setinterval in index.html as people don't like dynamically reloading blocks
Related
I have a made a quiz page, which checks whether the answer of the user is correct or not using a "checkans" function. I want to return a "Correct" message if the answer is correct and an "Incorrect" message if the answer is not correct. Now I can "kind of" do it, but not exactly what I want. Now it returns the message after redirecting to a whole new page, with the Question Box and everything else totally disappeared, only with the message.
I want the message to be shown on the same original question page, somewhere under the question box or within the question box, without redirecting to another page or refreshing the page, after submitting the answer. I don't know how to do it.
Here is my view:
class QuizView(generic.ListView):
template_name = 'geniusdennis/quiz.html'
queryset = Spanish.objects.all()
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# grab the max id in the database
max_id = Spanish.objects.order_by('-id')[0].id
random_id = random.randint(1, max_id + 1)
random_spanish_question = Spanish.objects.filter(id__gte=random_id)[0]
context['random_spanish_question'] = random_spanish_question
return context
Here is my function for checking the answer:
def checkans(request, spanish_id):
random_spanish_question = get_object_or_404(Spanish, pk=spanish_id)
query = request.GET.get('ans')
coreng = random_spanish_question.english_set.get()
if query == str(coreng):
return render(request, 'geniusdennis/quiz.html',{
'message': "Correct!",
})
else:
return render(request, 'geniusdennis/quiz.html', {
'message': "Incorrect.",
'correct_answer': "The correct answer is " + str(coreng),
})
And here is my HTML page:
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'geniusdennis/style.css' %}">
{% if random_spanish_question %}
<div class="flexcontainer" style="justify-content: center;">
<div class="sectiontitle">Quiz time
</div>
<div class="question_card">
<div class="question_word">{{ random_spanish_question }}</div>
<form action="/checkans/{{random_spanish_question.id}}/" method="get">{% csrf_token %}
<label for="ans">Answer:</label>
<input type="text" name="ans"/>
<input type="submit" value="Submit"/>
</form>
<input type="submit" value="Skip"/>
</div>
</div>
{% else %}
{% if message %}
<div class="message">
{{ message }}
</div>
<div class="ans">
{{ correct_answer }}
</div>
{% endif %}
{% endif %}
What you need is ajax, so you need some js code here.
<scrip src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script>
$('form').on('submit', function(e) { // or you can get the form by id if you set it
e.preventDefault(); // avoid to execute the actual submit of the form.
var form = $(this);
var url = form.attr('action');
$.ajax({
type: 'GET',
url: url,
data: form.serialize(), // serializes the forms elements.
success: function(data)
{
... // whatever you want to do
var alertMessage = data.message;
if (data.correct_answer) {
alertMessage += ' ' + data.correct_answer;
}
alert(alertMessage); // show response
}
});
});
</script>
html forms will go to action url. If you want some changes or functions in your page without reload, you need to use js.
Quite commonly in web applications, you need to display a one-time
notification message (also known as “flash message”) to the user after
processing a form or some other types of user input.
For this, Django provides full support for cookie- and session-based
messaging, for both anonymous and authenticated users. The messages
framework allows you to temporarily store messages in one request and
retrieve them for display in a subsequent request (usually the next
one). Every message is tagged with a specific level that determines
its priority (e.g., info, warning, or error).
for implementing messages refer to: https://docs.djangoproject.com/en/1.11/ref/contrib/messages/
I'm trying to load the data into json2 template as soon as there is new data available without refreshing the page but I'm unable to do that, this is what I tried till now main Function
#app.route("/")
def index1():
return render_template("index.html",gamest=get_games())
endpoint on the server that returns info.
#app.route("/sys_info.json")
def index():
return get_games()
jinja 2 scripts:
<script src="https://code.jquery.com/jquery-3.2.1.js"></script>
<div id="content">{{ index }}</div> {# this is the original system_info passed in from the root view #}
<script>
setInterval(function(){ // load the data from your endpoint into the div
$("#content").load("/sys_info.json")
},1000)
</script>
<div class="list-group">
{% for game in gamest %}
<a class="score-size text-xs-center nounderline list-group-item list-group-item-action" >
<div class="row">
<div class="col-xs-4">
{% if game["Batting_team_img"] %}
<img class="team-logo" src="/static/{{ game["Batting_team_img"] }}">
{% endif %}
{{ game["Batting team"] }} {{ game["runs10"] }}
</b>
<br>
{{ game["wickets10"] }}
</div>
I can see only change in the value in terminal but I can't see any changes in webpage data remains static, how can I fix this so data are changed dynamically in the website without refreshing page?
The data is requested but the html is not refreshed by the js script. You have to add the logic for the browser to load the data in the html. For example:
setInterval(function() {
// load the data from your endpoint into the div
$.getJSON("/sys_info.json", function (data) {
$.each(data, function (_, element) {
$('.list-group').append('<div>' + elment['Batting team'] + '</div>);
});
})
},1000)
You need the client browser to do the same you do on the server with jijna.
This question already has answers here:
How to redirect with Flask and jQuery
(2 answers)
Closed 6 years ago.
I am building a small web app in Flask, a code excerpt is below. Basically, I am trying to store some data in startsession and then move on to tagpage once this is achieved. But redirect is not working.
When I run TEST 1, it displays hello, world in the console but the main page looks the same.
When I run TEST 2, it displays the html in the console but the main page looks the same.
Here is what I have:
#app.route('/startsession', methods=['POST'])
def startsession():
_username = request.form['inputName']
session['user_name'] = _username
...
return redirect(url_for('tagpage'))
Then, either:
### TEST 1
#app.route("/tagpage")
def tagpage():
return "hello, world"
Or:
### TEST 2
#app.route("/tagpage")
def tagpage():
return render_template('tagpage.html', filename=filename)
Sample of what I see after clicking the button that triggers startsession:
How can I get the browser to actually go to http://localhost:5000/tagpage?
UPDATE:
Here is my JQuery script:
$(function(){
$("#btnStartSession").click(function(){
$.ajax({
url: '/startsession',
type: 'POST',
data: $('form').serialize(),
success: function(response){
console.log(response);
},
error: function(error){
console.log(error);
}
});
});
});
I guess the screenshot shows the output of console.log and thus I conclude that the POST is done in javascript, probably jQuery (waiting for an answer from the asker).
If this is the case, this is the expected behavior. The POST is done and the javascript receives the redirect and GET's the redirected resource.
And the javascript is logging the html of the redirected resource.
If you want to redirect the browser you can either do this manually in the javascript (after the POST is done) using:
window.location = "/tagpage";
Or let the browser do it for you, in this case, the POST must be done through a <form>.
I think Simon is on the right track here. You can find additional information in these previous questions about jquery, flask and redirects.
In short, you should probably just use normal html form like in the Flask documentation.
Template:
{% extends "layout.html" %}
{% block body %}
{% if session.logged_in %}
<form action="{{ url_for('add_entry') }}" method=post class=add-entry>
<dl>
<dt>Title:
<dd><input type=text size=30 name=title>
<dt>Text:
<dd><textarea name=text rows=5 cols=40></textarea>
<dd><input type=submit value=Share>
</dl>
</form>
{% endif %}
<ul class=entries>
{% for entry in entries %}
<li><h2>{{ entry.title }}</h2>{{ entry.text|safe }}
{% else %}
<li><em>Unbelievable. No entries here so far</em>
{% endfor %}
</ul>
{% endblock %}
View function:
#app.route('/add', methods=['POST'])
def add_entry():
if not session.get('logged_in'):
abort(401)
db = get_db()
db.execute('insert into entries (title, text) values (?, ?)',
[request.form['title'], request.form['text']])
db.commit()
flash('New entry was successfully posted')
return redirect(url_for('show_entries'))
New to flask here ... my problem is that I'm trying to check if a response is empty, and if so flash a message. With the below code, I can see that the redirect goes through and the subsequent GET responds with the correct html in dev tools, but the page is not loaded, it stays on the current page (which also happens to be layout.html, not sure if this is an issue, my intent is to simply reload this page to show the flashed message).
Relevant Flask:
#app.route('/')
def hello():
return render_template('layout.html')
#app.route('/query',methods=['POST'])
def query():
start=request.json['start']
end=request.json['end']
name=request.json['name']
sql="select some stuff"
data_list = []
stuff=cur.execute(sql)
for row in stuff:
data_list.append(row[0])
if not data_list:
flash('No balances for selected client/dates')
return redirect(url_for('hello'))
return json.dumps(data_list)
if __name__ == '__main__':
app.secret_key = 'secretkeyhere'
app.run(debug=True,host='127.0.0.1',port=8000)
Relevant portion of the html to avoid a wall of text
<body>
<div class="container">
{% with messages = get_flashed_messages() %}
{% if messages %}
{% for message in messages %}
<div class="flashed_message" role="alert">
<button type="button" class="close" data-dismiss="alert" aria- label="Close"><span aria-hidden="true">×</span></button>
{{message}}
</div>
{% endfor %}
{% endif %}
{% endwith %}
{% block content %}{% endblock %}
And lastly.... AJAX:
$(function(){
$("[type=submit]").click(
function(){
// event.preventDefault()
$(".container").hide()
var startdate=$('#datetimepicker1').val()
var enddate=$('#datetimepicker2').val()
var name=$('#mhh').val()
$.ajax({
type: "POST",
url: $SCRIPT_ROOT + "/query",
contentType: "application/json; charset=utf-8",
dataType:"json",
success: function(response) {
console.log('worked!')
return {'start':response.start,'end':response.end,'name':response.name}
},
error:function(){
console.log('didn\'t work')
}
})
})
});
From what I can see of your code it looks like you're redirecting the AJAX call. Essentially your AJAX call will load your index, and not the browser itself (which is what you want).
Inside your AJAX, try changing your error function to
error: function() {
document.location.reload()
}
Then, alter your if not data_list block to:
if not data_list:
flash('No balances for selected client/dates')
return Response(status=500)
I have gone through django and dropzone. I have implemented drag and drop feature of dropzone in django.
My template look like:
<form id="add-multiple" class="dropzone" action="{% url "name_add" %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
</form>
<button id="submit-all" type="submit" value="Submit" form="add-multiple">
Submit all files
</button>
<script src="{% static 'js/dropzone.js' %}"></script>
<script type="text/javascript">
Dropzone.options.myDropzone = {
// Prevents Dropzone from uploading dropped files immediately
autoProcessQueue : false,
paramName: "files",
init : function() {
var submitButton = document.querySelector("#submit-all")
myDropzone = this;
submitButton.addEventListener("click", function() {
myDropzone.processQueue();
// Tell Dropzone to process all queued files.
});
// You might want to show the submit button only when
// files are dropped here:
this.on("addedfile", function() {
// Show submit button here and/or inform user to click it.
});
}
};
</script>
Here, I am getting the css and uploading perfectly, but when I submit the form, it doesn't call the {% url "name_add" %} url. I mean, the form is not posted and it doesn't call that url.
I followed this tutorial https://amatellanes.wordpress.com/2013/11/05/dropzonejs-django-how-to-build-a-file-upload-form/ to achieve this.
First thing, my form is not being posted or it says it is not calling the url in form action. Second there is not any use of my form that I have created in forms.py to upload a file. In the tutorial also there is no use of form. Why is that and without form how form can be submitted because view requires form.
Can anyone help me?
in:
Dropzone.options.myDropzone = {
....
actually myDropzone is the camelized version of the HTML element's ID.
so the form id must be my_dropzone instead of add-multiple:
<form id="my_dropzone" class="dropzone" action...