I am making this program:
name = input("Enter your name: ")
age = input("Enter your age: ")
position = input("Your position in class: ")
print("I am",name,". I am",age,"years old. This time I got",position,"position
in my class.")
This outputs
I am Python Man . I am 13 years old. This time I got 1st position in my
class.
How can I enter this output into html, guys?
If you were to put...
I am Python Man . I am 13 years old. This time I got 1st position in my
class.
Into a .html file then load it, it'd work fine. If you want to format it properly with tags directly from the python file, you could change your print() line to, for example...
print("<p>I am",name,". I am",age,"years old. This time I got",position,"position
in my class.</p>")
There is several ways, and depends on what you really want to achieve, so I'll explain couple of options you have:
you can add any HTML tags you want in the string "as it's already
HTML that doesn't have any tags to format it" but you will have to
escape special characters that may break your HTML using built-in
Module " html"
you can also use third-party modules such as this which can generate HTML for you, and it's usage described briefly in the link.
The choice is simple if you have HTML knowledge and want to customize your HTML go for the first option, if not or you want easy solution go for the module.
I'm going to cut you some slack here. The text you have is already perfectly valid HTML. I think you actually want to display the text in a browser (jumping a few steps ahead). You will need a web framework for that; I'm using Flask here, but there are many, with Django being the other major framework (that takes a little more effort to set up).
from flask import Flask, request
app = Flask(__name__)
#app.route('/')
def homepage():
return("""<table>
<thead>
<th>Name</th>
<th>Age</th>
<th>Position</th>
<th></th>
</thead>
<tbody>
<form method ="post" action="{{ url_for('submit_answer') }}">
<input type="hidden" value="{{ csrf_token() }}" name="csrf_token">
<tr>
<td><input type="text" name="my_name" value=""></td>
<td><input type="text" name="my_age" value=""></td>
<td><input type="text" name="my_position" value=""></td>
<td><input type="submit" value="Submit"></td>
</tr>
</form>
</tbody>
</table>""")
#app.route('/submit_answer', methods=["GET", "POST"])
def submit_answer():
req = request.form.to_dict()
return "Hello {}, aged {}, your position is {}".format(req['my_name'],
req['my_age'],
req['my_position'])
if __name__ == '__main__':
app.run()
Run this and then type 127.0.0.1:5000 in the browser. There's a lot going on here, but hopefully enough to inspire you and keep you interested. You'll need to Google a lot. You can find more in the quickstart guide for Flask.
Related
I am trying to submit a form with Flask using dynamic field names for multiple check boxes within a form. The naming of the fields seems to work and they have the names I want, but when I try to use request.form.get() to get the information from the form using the dynamic field names it is just returning None, meaning that the dictionary that is returned does not contain the names of my fields. Here is my code:
The Form And Example of name
HTML
<form action="{{url_for('main.updatealleles', id=fish.id)}}" method="post">
<div id="updateAllelesBlock">
<table id="alleleTable" style="margin: auto; margin-top:20px;">
<tr>
<th>Name</th>
<th>Unidentified</th>
<th>Identified</th>
<th>Heterozygous</th>
<th>Homozygous</th>
<th>Hemizygous</th>
</tr>
{%for allele in alleles%}
<tr>
<th>{{allele.name}}</th>
<td><input type="checkbox" name = {{allele.name.replace(" ", "")+"Unidentified"}}</td>
<td><input type="checkbox" name = {{allele.name.replace(" ", "")+"Identified"}}</td>
<td><input type="checkbox" name = {{allele.name.replace(" ", "")+"Heterozygous"}}</td>
<td><input type="checkbox" name = {{allele.name.replace(" ", "")+"Homozygous"}}</td>
<td><input type="checkbox" name = {{allele.name.replace(" ", "")+"Hemizygous"}}</td>
</tr>
{%endfor%}
</table>
</div>
<button type="submit" class="btn btn-secondary" style="margin-top: 10px;">Update</button>
</form>
PYTHON
#bp.route("/fish/<id>/updatealleles/", methods=["GET", "POST"])
#login_required
def updatealleles(id):
fish = Fish.query.filter_by(id=id).first_or_404()
alleles = Allele.query.filter_by(fish=fish).all()
if request.method == "POST":
for allele in alleles:
print(request.form.get(f"{allele.name.replace(' ', '')}Unidentfied"), file=sys.stderr)
print(request.form.get(f"{allele.name.replace(' ', '')}Identfied"), file=sys.stderr)
#THIS IS ALWAYS PRINTING NONE, SAME WITH ALL OTHER FIELDS
#therefore these, and the other fields are being set to None rather than true/false
allele.unidentified = request.form.get(f"{allele.name.replace(' ', '')}Unidentified")
allele.identified = request.form.get(f"{allele.name.replace(' ', '')}Identified")
db.session.commit()
return redirect(url_for("main.updatealleles", id=fish.id))
return render_template('updatealleles.html', fish=fish, alleles = alleles, title = "Update Alleles")
The reason I need the dynamic name fields is because there could be any number of different allele objects (they are SQLAlchemy objects) and the table is there to set different attributes for each allele object to true or false, shown in the python example.
If there is a completely different way to do this that I am no aware of then I am also happy to try that.
I know there have been some similar questions to this, but I have tried all of their suggestions and none of them have worked for me, so any help would be greatly appreciated and let me know if you need any more information.
Okay I have the solution. It turns out even though the names appeared to be working when inspected, the jinja2 string was actually returned as unclosed when the form was requested extra information was included in the name.
All I had to do to fix that was to add single quotation marks, either side of the id, so now it looks like this, for example:
<td><input type="checkbox" name = '{{allele.name.replace(" ", "")+"Unidentified"}}'</td>
and then the python can work like this:
allele.unidentified= request.form.get(f"{allele.name.replace(' ', '')}Unidentified") == "on"
And the same for each other field.
This question already has answers here:
Sending data from HTML form to a Python script in Flask
(2 answers)
Closed 1 year ago.
I've created a form with flask. This is the python code that handles the requests that come from this form:
#app.route("/submitclips/", methods=['GET', 'POST'])
def submitclips():
print(request)
print(request.method)
result = request.form.to_dict(flat=False)
print(result)
print(request.data)
HTML code:
<form action="/submitclips" method="POST">
<input type="hidden" name="taskpath" value="paththotask">
<table>
<th>Video</th>
<th>Mute</th>
<th>Delete</th>
<th>Keep</th>
<tr>
<td>
<video width="320" height="240" controls>
<source src="videosource.mp4" type="video/mp4">
</video>
</td>
<td>
<input type="radio" id="name$mute" name="name" value="mute">
</td>
<td>
<input type="radio" id="name$delete" name="name" value="delete">
</td>
<td>
<input type="radio" id="name$keep" name="name" value="keep" checked>
</td>
</tr>
</table>
<input type="submit">
</form>
This is a table and has more than one row, I changed the values to make it more readable. I guarantee that all names are unique where they are supposed to be unique though.
It has some code below it, but it crashes there because the form seems to be empty. I have checked the HTML and it's all correct, all inputs have a name. I also recorded the network traffic on google chrome to test this and I can see that all data in the form is present in the request data. So I'm pretty sure it's correct on the front-end. The problem is that it just doesn't show up in this method. In the code you can see several print statements and all of these show me empty data and not the data that I could see in my chrome browser. The method is GET, I don't know if it should be GET. In HTML I selected it to be a POST method, but if I remove the GET option from the python code, it gives me a "method not allowed" error.
I don't know what to do, this is some older code that used to work on my windows machine. I didn't change anything about it, but now I'm working on linux and it's completely broken, none of the forms work, it's all empty data.
Here you have mentioned that the endpoint /submitclips has methods GET and POST. It means that whenever i hit the url "baseurl/submitclips" then this function will be executed. Inside the function you have not specified for which method you will have what response, i.e if i call the endpoint using GET or POST you will process it the same way. This is not a good practice. I suggest you put something like :
if request.method == 'POST' or if request.method == 'GET' to separate the execution based on the type of method.
Now coming to the HTML, you must have the HTML from where you are sending the request to the server. If that data is coming from a form, then as part of the form you can add two attributes,
<form method="post"> and <form action="/submitclips"> to specify that on submit of this form,you will be sending the form data through POST method to the "/submitclips" url. It will look like this.
<form method="post" action="/submitclips"">
For the Server side,
def submitclips():
if request.method == 'POST' :
print(request)
print(request.method)
result = request.form.to_dict(flat=False)
print(result)
print(request.data)
It should work after that.
I have found the error. My HTML code would submit the form to "/submitclips" while the python code received requests from "/submitclips/". I don't know why this is wrong though, the tutorial that I followed for flask told me specifically that putting a slash at the end meant that it could receive requests from both "/submitclips" and "/submitclips/". This also worked earlier on my windows machine, but doesn't work anymore on my linux machine. I'm glad it's solved, but if anyone has an explanation for why this is wrong, feel free to answer.
I look for answers but It was all about php. I got this index.html:
<form method="post">
<input type="checkbox" name="opts" value="opt1" opt[0]> option 1<br>
<input type="checkbox" name="opts" value="opt2" opt[1]> option 2<br>
<input type="checkbox" name="opts" value="opt3" opt[2]> option 3<br>
<br>
<input name="" type="submit" value="Save" >
</form>
and this main.py
import webapp2
import cgi
import os
import jinja2
from gaesessions import get_current_session
class MainHandler(webapp2.RequestHandler):
def get(self):
session=get_current_session()
opt=session.get('opt',[]) jinja_environment=jinja2.Environment(autoescape=True,loader=jinja2.FileSystemLoader(os.path.join(os.path.dirname(__file__),'templates')))
tpi_vars={"opt":opt}
template=jinja_environment.get_template('index.html')
self.response.write(template.render(tpi_vars))
def post(self):
opt=self.request.get("opt", allow_multiple=True)
session=get_current_session()
session['opt']=opt
I want to store checked checkboxes and get them. How can I make this possible?
Your Python code seems correct, apart from one weird bug whereby the line using jinja_environment is concatenated to the previous one (?!).
Your Jinja template seems wrong as it doesn't look in the environment, nor does it mark any checkbox as checked. I would recommend something like:
<input type="checkbox" name="opts" value="opt1" {{ops.get('opt1','')}>
option 1<br>
and so on -- the double braces to check into the environment, and a dictionary ops that you could prepare on the Python side.
Right now what you get as opt is a list such as e.g ['opt1'] if that's the only checked checkbox at post time. You could deal with that in the Jinja side, but it's easier on the Python side, I think. So, instead of:
tpi_vars={"opt":opt}
I'd do:
tpi_vars={'ops': dict.fromkeys(opt, 'checked')}
Of course, you don't have to do it just before you render the Jinja2 template -- you could do this list-to-dict translation at any time. But since it is about presentation issues, this seems a good place for it.
Using Flask and Python, I have a website running on localhost which allows user to select a specific month to download a report for. Based on the selected month, I will than have my web scraping file imported which retrieves the data from another website (requires login). My web scraping script uses Mechanize.
Here is the portion of code where my web scraping file (webscrape.py) is imported after the download button is clicked (the selection is done on office.html):
#app.route('/office/', methods=['GET','POST'])
def office():
form=reportDownload()
if request.method=='POST':
import webscrape
return render_template('office.html', success=True)
elif request.method=='GET':
return render_template('office.html', form=form)
In the render_template method,success=True is passed as an argument so that my office.html script will display a success message, if not (when it is a GET request), it will display the form for user selection. Here is my script for office.html:
{% extends "layout.html" %}
{% block content %}
<h2>Office</h2>
{% if success %}
<p>Report was downloaded successfully!</p>
{% else %}
<form action="{{ url_for('office') }}" method="POST">
<table width="70%" align="center" cellpadding="20">
<tr>
<td align="right"><p>Download report for: </p></td>
<td align="center"><p>Location</p>
{{form.location}}</td>
<td align="center"><p>Month</p>
{{form.month}} </td>
<td align="center"><p>Year</p>
{{form.year}} </td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td align="center">{{form.submit}} </td>
</tr>
</table>
</form>
{% endif %}
{% endblock %}
The problem I have is when I want to do further downloads, i.e. after downloading for the first time, I go back to the office page and download a report again. On the second try, the success message gets displayed but nothing gets downloaded.
In my web scraping script, using mechanize and cookiejar, I have this few lines of code in the beginning:
br = mechanize.Browser()
cj = cookielib.LWPCookieJar()
br.set_cookiejar(cj)
and I proceed with the web scraping.
When running the web scraping file on my Terminal (or command prompt), the script executes without any problems, even if I run it a second or third time. So I think that it may be a problem with the website codes.
Any suggestions will be appreciated! I have tried different ways of resolving the problem such as using return redirect instead, or trying to clear the cookies in cookiejar. None has worked so far, or I may be using the methods wrongly.
Thank you in advance!
Once your Flask app is started it only imports each package once. That means that when it runs into import webscrape for the second time it says “well, I already imported that earlier, so no need to take further action…” and moves on to the next line, rendering the template without actually starting the script.
In that sense import in Python is not the same as require for other languages (such as PHP; by the way, it would be closer to require_once in PHP).
The solution would be to make your scraper an object (class) and instantiate it each time you need it. Then you move the import to the top of the file and inside the if request.method=='POST' you just create a new instance of your web scraper.
FIXED! updated with working code
I have been going about trying to make this auto login thing working for me.
Do note I'm still a Python novice at this point.
The following is the html code I found when I inspected the relevant form:
<form action="/cgi-bin/netlogin.pl" method="post" name="netlogin">
<tr>
<td><div align="right">Intranet userid:</div></td>
<td><input type="text" size="20" maxlength="50" name="uid" id="uid" class="formField" /></td>
</tr>
<tr>
<td><div align="right">Wachtwoord:</div></td>
<td><input type="password" size="20" maxlength="50" name="pwd29296" class="formField" autocomplete="off"/></td>
</tr>
<tr>
<td> </td>
<td><input type="submit" name="submit" value="Login" /></td>
</tr>
</form>
I start off with getting the portal html content to find the right "pwdXXXX" variable. As with every refresh, the ID for the password form changes. To my understanding this, and the regex works.
It does go wrong when trying to pass the password. Which makes me think I got it wrong with the form its keys? I have absolutely no clue. I also tried using the urllib2 approach instead of using mechanize. No result either.
Working code:
url = "https://netlogin.kuleuven.be/cgi-bin/wayf2.pl?inst=kuleuven&lang=nl&submit=Ga+verder+%2F+Continue"
br = mechanize.Browser()
br.set_handle_robots(False)
br.open(url)
br.select_form(name = "netlogin")
form = str(br.form)
uID = "uid"
dynamic_pwID = re.findall(r"(pwd\d+)", form) #pwID changes when page is refreshed
pwID = dynamic_pwID[0]
br[uID] = "xxxx"
br[pwID]= "xxxx"
res = br.submit()
A part of your problem may well be that since you close the socket that you read the page with urllib with your mechanize session will have a different ID and so require a new token.
You will need to keep a single connection open for the duration of the session. So I think that you will need to parse the contents of the reply to br.read() to find your value for pwID.
Comment From OP:
I left out the urllib part and it's working now. I used str(br.form) instead of br.read() though.