Im trying to get a basic app working in Django that incorporates AJAX.
The app will take a domain name and will then send it to the server, which will do a dns lookup on it and then send the response back via AJAX to the client.
Views
from django.http import *
from django.shortcuts import render_to_response
from django.template import RequestContext
import sys
import os
import socket
def main(request):
if request.method == 'POST':
dig_input = request.POST['digInput']
digoutput = socket.gethostbyname(dig_input)
return render_to_response('digajax.html', {'response': digoutput}, context_instance=RequestContext(request))
else:
return render_to_response('digajax.html', context_instance=RequestContext(request))
URLs
url(r'^digajax$', 'digajax.views.main'),
Templates
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script type='text/javascript' src='http://code.jquery.com/jquery-1.8.2.js'></script>
<script type="text/javascript">
function send_request(){
$.get(location.href, function(data){
$("#output").html(data.output);
});
}
</head>
<body>
<form method="post" name="diginput form" action="/digajax">
{% csrf_token %}
<input name="digInput" id="digInput" type="text">
<input type="button" onclick="send_request();" value="Request this page with AJAX">lookup</input>
</form>
{% if response %}
<div id="output">
<p>{{ response|linebreaksbr }}</p>
</div>
{% else %}
<p>no</p>
{% endif %}
</body}
</html>
Without AJAX everything is working. Now that I want to use AJAX Im not what what code I should add to each section.
Any help would be really appreciated...............
Django provides an method on the request object your view is passed which will tell you whether the request was made via XmlHttp, request.is_ajax().
If that method returns true, you probably want to return only the fragment of the page you want to update, instead of the whole page.
If that method returns false, you probably want to return the entire page, since the user either has JavaScript turned off, or there was some type of error which caused the view to be requested normally.
So, your view should look like:
def main(request):
if request.method == 'POST':
dig_input = request.POST['digInput']
digoutput = socket.gethostbyname(dig_input)
if request.is_ajax():
return HttpResponse("<p>%s</p>" % digoutput)
else:
return render(request, 'digajax.html', {
'response': digoutput
})
else:
return render(request, 'digajax.html')
Your JavaScript code should be look like:
<script type="text/javascript">
function send_request(){
$.get(location.href, function(data){
$("#output").html(data);
});
}
</script>
Related
This html template from my online class executes as intended, but why? It seems like it is executing out of order:
It calls my python form class using Django's syntax {{form}} to inject the blank fields for the user to fill out (name, email, textbox)
The user can enter and hit the "Submit" button
but then (confusingly) is that it seems the {{form}} class is called again with the entry information as it then successfully prints out user input to the terminal. Why is this?
html in templates.py
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#4.3.1/dist/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
</head>
<body>
<h1>fill out the form</h1>
<div class="container">
<form method="POST">
{{form}}
{% csrf_token %}
<input type="submit" class="btn btn-primary" value="submitme">
</form>
</div>
</body>
</html>
Form class in views.py
def form_name_view(request):
form = forms.FormName()
if request.method == "POST":
form = forms.FormName(request.POST)
if form.is_valid():
print("VALIDATION SUCCESS")
print("NAME: " + form.cleaned_data['name'])
print("EMAIL: " + form.cleaned_data['email'])
print("TEXT: " + form.cleaned_data['text'])
return render(request, 'first_app/form_page.html', {'form' : form})
Supplemental: the url that uses the html template and my forms class
from django.urls import path
from first_app import views
urlpatterns = [path('formpg', views.form_name_view, name = 'formpg')]
As mentioned in the Django form docs,
Form data sent back to a Django website is processed by a view, generally the same view which published the form. This allows us to reuse some of the same logic.
So your code is executing in the correct order:
When the page is first loaded, a GET request is made and form_name_view() is called. This creates an empty Form object and renders it into a html form with render(request, 'first_app/form_page.html', {'form' : form})
When the html form is submitted, a POST request is made and a new Form object is made with the data sent from the web browser. As in the example, you may want to direct users to another page if their submitted form is valid.
This is my code on html file on a django project. I am using this code on this function
def home(request):
context = {
'post': posts
}
return render(request,'blog/home.html',context
It does not display anything when I see page source it's just bacis html code head and body empty
<html>
<head>
<title> </title>
</head>
<body>
{% for post in posts %}
<h1>{{post.title}}</h1>
<p>By {{post.author}} on {{post.date_posted}}</p>
<p>{{post.content}}</p>
{% endfor %}
</body>
</html>```
It is a typo. You need to change the context in your view from:
context = { 'post': posts }
to
context = { 'posts': posts }
^^^^^^^
Am very much new to Flask & Python, so want to understand/clear my concepts. I have a webpage which i created using flask & wtforms. Html page is very simple having just single field & a submit button. I want to call a python script (test.py) itself or python function(pythonfunction()) when submit button is clicked. Also Is there a way from the webpage,whatever i enter , i can pass as an attribute to that python script (test.py)? help appreciated
**app.py**
from flask import Flask , render_template,flash,redirect,url_for,session,logging,request
from wtforms import Form,StringField,TextAreaField,PasswordField,validators,SelectField,TextAreaField
from wtforms.widgets import TextArea
import subprocess
import test
app=Flask(__name__)
#app.route ('/')
def index():
return render_template('home.html')
class testpython(Form):
testenter=StringField('Enter something')
#app.route ('/testpage',methods=['GET','POST'])
def testpage():
form=testpython(request.form)
return render_template('testpage.html',form=form,python=testfunc(testenter))
if __name__ == '__main__':
app.run(debug=True)
**test.py**
def pythonfunctiontest (self):
print data #<something i can print here from that text field in webpage>
return "all good"
**testpage.html**
{% extends 'sec_layout.html'%}
{% block body %}
{% from "includes/_formhelpers.html" import render_field %}
<form method="POST" action ="">
<div class="form-group">
{{render_field(form.testenter,cols="1", rows="5",class_="form-control")}}
</div>
<div class="input-bar-item input-bar-item-btn">
<button class="btn btn-info">Submit</button>
</div>
</form>
{% endif %}
{% endblock%}
sec_layout.html
<!DOCTYPE <!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>MY PAGE-TEST</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
</head>
<body>
{% include 'includes/_navbar.html' %}
<div class= "container">
{% block body %}{% endblock%}
</div>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" </script>
</body>
</html>
The question is very general so I will try and give you a steer and perhaps you might revisit this question later with a little more clarity.
Flask asks a server and renders webpages. I.e. it executes some code on the server and passes it to the client web browser. The client web browser can then execute client side code (i.e. Javascript) as the user is browsing and can pass data back to the server using submit forms (to different Flask routes) or via JavaScript AJAX requests (again to other Flask routes). So if you want to execute python script based on some input you will need a separate route.
Here is a simple example of an index page and a second route that will execute something else:
#app.route('/index')
def index():
""" very basic template render """
return render_template('index.html')
#app.route('/data-submit', methods=["POST"])
def calc():
data = request.form.information.data
# do something with data..
x = data + data
return render_template('new_page.html', x)
========= (index.html)
<html>
<body>
<form action="{{ url_for('app.calc') }}" method="POST">
<input name="information" type='text'>
<button name="submit">
</form>
</body>
</html>
Wrap whatever temp.py is doing in a function.
Place it in the same directory as flask.py. Call import temp in flask.py, then use temp.myfunction().
I am new to Flask and want to create a On/Off toggle button on my website. I was wondering if and how this is possible also including a dynamic label. The following picture shows what I have in mind:
I was thinking about using a wtfforms SubmitField but I don't quite know how to implement this dynamic behavior between my routes.py file and my html template. I was thinking something like this:
forms.py:
from flask_wtf import FlaskForm
from wtforms import SubmitField
class PowerSwitchForm(FlaskForm):
power_switch = SubmitField("ON")
routes.py:
from flask import render_template, flash, redirect, url_for
from app import app
from app.forms import PowerSwitchForm
#app.route('/power', methods=['GET', 'POST'])
def power():
power_switch = PowerSwitchForm()
if power_switch.power_switch.label.text == "ON" and power_switch.validate():
flash("Power has been turned ON")
power_switch.power_switch.label.text = "OFF"
return redirect(url_for('power')
elif power_switch.power_switch.label.text == "OFF" and power_switch.validate():
flash("Power has been turned OFF")
power_switch.power_switch.label.text = "ON"
return redirect(url_for('power')
return render_template('power.html', form0=power_switch)
power.html:
<!DOCTYPE html>
{% extends "base.html" %}
{% block content %}
<h2>Power switch</h2>
<form action="" method="post" novalidate>
{{ form0.hidden_tag() }}
{{ form0.power_switch() }}
</form>
{% endblock %}
You can use jquery to handle the desired operation when the toggle button is clicked. Also, if there is a backend process that should be performed when the button is toggled, ajax can be used. This answer demonstrates both. bootstrap-toggle is a library that enables simple implementation of a toggle. To use, copy the header tag values below:
Simple toggle that displays "toggled" or "untoggled":
<html>
<body>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/js/bootstrap.min.js"></script>
<link href="https://gitcdn.github.io/bootstrap-toggle/2.2.2/css/bootstrap-toggle.min.css" rel="stylesheet">
<script src="https://gitcdn.github.io/bootstrap-toggle/2.2.2/js/bootstrap-toggle.min.js"></script>
</head>
<input type="checkbox" class='toggle' checked data-toggle="toggle">
<div class='status'>Toggled</div>
</body>
<script>
$(document).ready(function() {
$('.toggle').click(function() {
var current_status = $('.status').text();
if (current_status === 'Untoggled'){
$('.status').html('Toggled');
}
else{
$('.status').html('Untoggled');
}
});
});
</script>
</html>
Toggle that triggers backend script for both "toggled" or "untoggled":
In the template, slightly change the script:
<script>
$(document).ready(function() {
$('.toggle').click(function() {
var current_status = $('.status').text();
$.ajax({
url: "/get_toggled_status",
type: "get",
data: {status: current_status},
success: function(response) {
$(".status").html(response);
},
error: function(xhr) {
//Do Something to handle error
}
});
});
});
</script>
Then, in your app, create a route /get_toggled_status:
#app.route('/get_toggled_status')
def toggled_status():
current_status = flask.request.args.get('status')
return 'Toggled' if current_status == 'Untoggled' else 'Untoggled'
This example does the same thing as the pure html/jquery solution, however, it does demonstrate how the backend can be communicated with when using the toggle.
I am also new to Flask. And here is the pure python code with flask that I've tried.
Looks it work.
in templates/demo.html :
{% extends "bootstrap/base.html" %}
{% import "bootstrap/wtf.html" as wtf %}
{% block content %}
<div class="page-header">
{{ wtf.quick_form(form) }}
</div>
{% endblock %}
in demo.py :
from flask import Flask, render_template, redirect, url_for
from flask_bootstrap import Bootstrap
from flask_wtf import FlaskForm
from wtforms import SubmitField
class PowerState(FlaskForm) :
state = SubmitField('OFF')
app = Flask(__name__)
Bootstrap(app)
app.config['SECRET_KEY'] = 'YOUR SECRET KEY'
#app.route('/', methods=['GET', 'POST'])
def home() :
form = PowerState()
if form.validate_on_submit() :
if form.state.label.text == 'OFF' :
PowerState.state = SubmitField('ON')
elif form.state.label.text == 'ON' :
PowerState.state = SubmitField('OFF')
return redirect(url_for('home'))
return render_template('demo.html', form=form)
then run :
flask run
Regards, Alex.Wu
This question already has answers here:
Flask-WTF - validate_on_submit() is never executed
(8 answers)
Closed 4 years ago.
Here is the class I created, model of the flask mega tutorial's RegistrationForm
class eyeReaderInput(FlaskForm):
article = StringField('Article')
submit = SubmitField('Enter')
And I've implemented that class in this view:
#app.route('/eyereader', methods=['GET', 'POST'])
def eyereader():
form = eyeReaderInput()
sTuple = ()
if form.validate_on_submit():
string = wikipedia.page(form.article.data)
for chunk in textwrap.wrap(string, 15):
sTuple += (chunk,)
return render_template('eyereader.html', string = sTuple, form = form)
else:
return render_template('eyereader.html', form = form)
with this being my template of eyereader.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{% if string %}
<p><span>
{% for s in string %}
[{{s}}]<pre class="tab"></pre>
{% endfor %}
</span></p>
{% else %}
<p>Please input an article name</p>
<form action = "" method = "post">
<p>{{ form.article.label}}<br>
{{ form.article() }}</p>
<p>{{ form.submit() }}</p>
</form>
{% endif %}
</body>
</html>
What I'm hoping to do is for the user to initially access the eyereader site using a 'GET' request (which is what happens when I look at my console), and once the user inserts the wikipedia article he wishes to read, it sends a 'POST' request with a new string parameter which will make {% is string %} true and instead show the wikipedia text.
However when I'm testing this, both 'GET' and 'POST' requests end up going to the input page. Does anyone know what I may be able to change to get this to work? Thanks.
Option #1: Use two templates to handle the conditional content, tying each template to a different form action (GET/POST).
#app.route('/eyereader')
def show_template():
return render_template("eyereader.html")
Option #2: Use JavaScript to dynamically populate content as needed.
<script type="text/javascript">
$('#my_object').on('change', function() {
var selected = $( "#my_object condition:true" ).text();
if(selected == "yes")
$(Do_Something_Here)
});
</script>