I am trying to get data and file from the following HTML template:
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>File Upload Example</title>
<style>
body {
margin: 0;
}
.center {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
font-size: 16px;
}
</style>
</head>
<body>
<div class="center">
<form method="POST" action="/upload" enctype="multipart/form-data">
<table>
<tr>
<td class="lbl"><label for="sub_id">Subject Id:</label></td>
<td><input class="fld" id="sub_id" type="text" placeholder="01" required></td>
</tr>
<tr>
<td class="lbl"><label for="sub_first_name">First Name:</label></td>
<td><input class="fld" id="sub_first_name" type="text" placeholder="John" required></td>
</tr>
<tr>
<td class="lbl"><label for="sub_last_name">Last Name:</label></td>
<td><input class="fld" id="sub_last_name" type="text" placeholder="Appleceed" required></td>
</tr>
<tr>
<td class="lbl"><label for="files">File upload:</label></td>
<td><input class="fld" name="file" type="file"></td>
</tr>
</table>
<input type="submit" />
<!--<button type='submit' name='selectionsubmit'>Submit</button>//-->
</form>
</div>
</body>
</html>
I am parsing this through flask #app.route:
#app.route("/upload", methods=["GET", "POST"])
def home():
if request.method == "POST":
file = request.files["file"]
data = jsonify(request.form).json()
print(data, flush=True)
when I try to print data, it returns an empty dict. How can I extract the data from HTML with the request, to get, for example, the value of sub_last_name with something like data.form['sub_last_name'] after form submit? Thanks
The content of an input field is accessed via the name attribute of the specific element defined in the HTML template. The reason you only get the data of the file field is that you only defined this attribute for said input field.
To get the data of the other fields, specify an attribute name.
<input type="text" name="sub_last_name" />
You can then query the data as usual and known from the dict type within the endpoint. So you can also ask whether the respective key is included.
sub_last_name = request.form['sub_last_name']
If you are not sure whether the attribute will be passed, you want to specify a default value or convert the type on request, you can also use get. In this case no KeyError is raised, but None or the optional defined default value is returned if the name of the input field is not found.
The default return value is of type str. However, if you also pass the type attribute, the input will be converted as desired. If the type change fails, the default value is returned.
Related
I have a problem with clicking an element using XPath in selenium. Here is the HTML element for the problem :
<label for="file" class="pb default" style="display: inline-block;margin: 5px 10px;">Select File</label>
Do you know the solution for this? Any response is really appreciated.
UPDATE :
here is the whole source code for the problem
<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=utf-8">
<BASE HREF="http://1.1.1.19/webclient/utility">
<link rel=stylesheet type="text/css" href="../webclient/skins/skins-20190807-1904/iot18/css/filex.css">
</head>
<body style="background: transparent; background-color: transparent">
<form name="IMPORT" id="IMPORT" enctype="multipart/form-data" method="post">
<input type="hidden" NAME="componetId" VALUE="itemimage_3_1-if">
<input type="hidden" NAME="controlId" VALUE="itemimage_3_1">
<table width="100%" cellspacing="0" align="center" class="maintable">
<tr>
<td align="left" style="white-space: nowrap;">
<label for="file" class="pb default" style="display: inline-block;margin: 5px 10px;">Select File</label>
<input id="fileName" onmousedown="" type="text" value="" class="fld fld_ro text ib" readonly size="50"/>
<input id="file" type="file" name="value" title="Specify a New File" onchange="" size="35" class="text" style=" width: 0.1px;height: 0.1px !important;fileStyle: 0;overflow: hidden;position: absolute;z-index: -1;opacity: 0;" value="" onclick="if(!parent.undef(parent.firingControl) && parent.firingControl.id==this.id){parent.sendEvent('clientonly','clickFileButton', this.id)}">
</td>
</tr>
</table>
</form>
</body>
<script>
document.querySelector('#file').addEventListener('change', function(e){
document.querySelector('#fileName').value = e.currentTarget.files[0].name;
});
</script>
</html>
Can try with //label[#for='file'] or //label[#for='file'][text()='Select File']
If this is not working maybe you are targeting the wrong element or you are not waiting enough before it appears. When dealing with uploading files, I target the input with type file //input[#type='file'], not the label, you may need to provide bigger part of your HTML.
if class=pb default is a unique class in the web-page then try this out.
driver.driver.find_element(By.XPATH,'//*[#class="pb default"]').click()
or you can search by text Select File
driver.find_element(By.XPATH,'//*[contains(text(),"Select File")]').click()
Well No, you don't click on a <label> element. However, you may require to locate the <label> element for other purposes.
To identify the <label> element you can use either of the following Locator Strategies:
Using css_selector:
element = driver.find_element(By.CSS_SELECTOR, "label.pb.default[for='file']")
Using xpath:
element = driver.find_element(By.XPATH, "//label[#class='pb default' and text()='Select File']")
Update
Element can be within an <iframe> or within a #shadow-root. Otherwise the locator works perfecto:
Not a very experienced user with python here, just picked up python while staying at home. I was looking into integrating the output of flask-table to a website. The following is my python code that creates a simple table for my website.
from flask_table import Table, Col
app = Flask(__name__)
class ItemTable(Table):
name = Col('Name')
description = Col('Description')
Class Item(object):
def __init__(self, name, description):
self.name = name
self.description = description
items = [dict(name='Name1', description='Description1'),
dict(name='Name2', description='Description2'),
dict(name='Name3', description='Description3')]
table = ItemTable(items)
#app.route("/")
def hello():
return render_template('index.html', tStrToLoad=table.__html__())
if __name__ == "__main__":
app.run()
and my html code that takes tStrToLoad from the python code above to display.
<html>
<head>
<title>Test Flask Table</title>
<style>
body
{
background-color: #000000;
color: #FFFFFF;
font-family:Verdana;
font-size:16px;
}
table, th, td
{
border: 1px solid #0088ff;
border-collapse: collapse;
padding: 3px;
font-family:Verdana;
font-size:12px;
text-align: left;
}
</style>
</head>
<body>
a simple test table
<br/><br/>
{{ tStrToLoad }}
</body>
</html>
And instead of showing a table with the data, I have the following output in a black background
a simple test table
<table> <thead><tr><th>Name</th><th>Description</th></tr></thead> <tbody> <tr><td>Name1</td><td>Description1</td></tr> <tr><td>Name2</td><td>Description2</td></tr> <tr><td>Name3</td><td>Description3</td></tr> </tbody> </table>
Upon further investigating, I did a view page source, this is my actual html code that arises from this.
<html>
<head>
<title>Test Flask Table</title>
<style>
body
{
background-color: #000000;
color: #FFFFFF;
font-family:Verdana;
font-size:16px;
}
table, th, td
{
border: 1px solid #0088ff;
border-collapse: collapse;
padding: 3px;
font-family:Verdana;
font-size:12px;
text-align: left;
}
</style>
</head>
<body>
a simple test table
<br/><br/>
<table>
<thead><tr><th>Name</th><th>Description</th></tr></thead>
<tbody>
<tr><td>Name1</td><td>Description1</td></tr>
<tr><td>Name2</td><td>Description2</td></tr>
<tr><td>Name3</td><td>Description3</td></tr>
</tbody>
</table>
</body>
</html>
My question is how do I format it correctly in my python script such that it sends < and > instead of & lt; and & gt;
If you're confident none of the data in the table has un-validated user input then tell Jinja not to escape the html:
{{ tStrToLoad | safe }}
However you may wish to avoid using Flask-tables, and just pass the items list yourself. The template code can become more generic if you also pass some headers in a separate list:
headers = ['Name','Description']
return render_template('index.html',
headers = headers,
objects = items)
Then manually build the table:
{% if objects %}
<table id='result' class='display'>
<thead>
<tr>
{% for header in headers %}
<th>{{header}}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for object in objects %}
<tr>
{% for k, val in object.items() %}
<td>{{val}}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
As you can see, this prevents you from having to hard-code any values into the template.
The syntax of this table is also compatible with datatables, so you if you load the CSS and JS files as per the zero configuration example then your table becomes prettier and can have a builtin search bar and pagination. Let me know if you need further direction on how to do this.
I have 2 scripts. One is my main.py script where it will call my other script to print an HTML page. The second script is html_pages.py. I'm trying to print an HTML page by importing html_pages.py and calling the welcome_page or login_page function.
Whenever I try to reach the page it says "Internal error". This was working previously when I had the login_page and welcome_page as a string stored in the main script. But it doesn't work when I try to call the function from a different script.
my main.py script contains:
#!/usr/bin/python3
import html_pages
if "HTTP_COOKIE" in os.environ :
cookie_info = os.environ["HTTP_COOKIE"]
cookies = cookie_info.split(';')
for cookie in cookies:
cookie_split = cookie.split('=')
cookie_dict[cookie_split[0].strip()] = cookie_split[1].strip()
CookieUsername = cookie_dict.get('username')
CookiePassword = cookie_dict.get('password')
CookieToken = cookie_dict.get('CSRFtoken')
#Connect to the database
import pymysql
conn = pymysql.connect(db='project2', user='algarcia1', passwd='root', host='localhost')
c = conn.cursor()
#Collect info about the user
query = "SELECT * FROM bank WHERE username='{CookieUsername}'"
c.execute(query.format(CookieUsername=CookieUsername))
conn.commit()
user = c.fetchone()
print(html_pages.welcome_page(user[0],user[3],user[4]))
else:
cookie_dict["username"] = "undefined"
cookie_dict["password"] = "undefined"
print(html_pages.login_page())
My HTML_pages.py script looks like this:
#!/usr/bin/python3
#Create a login HTML page
def login_page(status):
loginpage = """Content-Type: text/html
<!DOCTYPE html>
<!-- HTML code to send a POST request to login.py -->
<html>
<head>
<title>Safe Bank Website</title>
</head>
<body>
<form action="login.py" method="POST">
<h1>Safe Bank Website</h1>
<strong>Username:</strong><br>
<input type="text" name="username"><br>
<strong>Password:</strong><br>
<input type="text" name="password"><br>
<strong>CSRF token:</strong><br>
<input type="text" name="CSRFtoken"><br><br>
<input type="submit" value="Submit">
</form>
</body>
</html>"""
print(login_page.format())
def welcome_page(username, chequings, savings):
#Create a welcome HTML page
welcomepage = """Content-Type: text/html
<!DOCTYPE html>
<html>
<head>
<style>
table, th, td {{ border: 2px solid black; text-align: left;}}
th, td {{ padding: 5px; }}
</style>
</head>
<body>
<h2>Welcome {cookie_info}!</h2>
<table style="width:100%">
<tr>
<th>Chequings</th>
<th>Savings</th>
</tr>
<tr>
<td>{chequings}</td>
<td>{savings}</td>
</tr>
</table>
Transfer money
</body>
</html>"""
print(welcome_page.format(cookie_info=username,chequings=chequings,savings=savings))
There are so many good python Web-Frameworks like Flask or Django. That make it easy so build webpages in a secure way. Especially Flask is very easy to use. Try them out and look how such frameworks do it.
In most cases it's more solid for future use to use a framework where you have a good structure.
I'am trying to Update existing objects from a database with a form.
What I need to obtain is :
1 displaying the data to be modified, 2, change the data with the new ones 3, display the new one.
I managed step 1 but its a mystery for step 2. Could you give me a hand ?
Here is my code :
Views.py
`def modec(request, etatcivil_id):
if not request.user.is_authenticated():
return render_to_response('cv/connexionrequired.html')
k = request.user.email
if request.method == 'POST':
ec = Etatcivil.objects.get(id=etatcivil_id)
form = EtatCivilForm(data=request.POST, instance=ec)
form.auteur=k
print "Product Post"
if form.has_changed():
print "form has changed"
if form.is_valid():
print "Display Form"
form.save(commit=False)
fom.save()
return HttpResponseRedirect('/cv/creer')
else:
eta = Etatcivil.objects.get(id= etatcivil_id)
form = EtatCivilForm(eta.__dict__)
args = {}
args.update(csrf(request))
args['form'] = form
return render_to_response('cv/modec.html', args)`
Model.py
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager
from django.conf import settings
class MyUserManager(BaseUserManager):
def create_user(self, email, password=None):
if not email:
raise ValueError('Users must have an email address')
if not username: username = email.split('#')[0]
user = self.model(
email= MyUserManager.normalize_email(email))
user.set_password(password)
user.save(using=cv._db)
class MyUser(AbstractBaseUser):
email = models.EmailField(max_length=254, unique=True, db_index=True)
registration = models.DateField(auto_now_add=True)
objects = MyUserManager()
USERNAME_FIELD = 'email'
class Meta:
unique_together = ('email', )
class Etatcivil(models.Model):
Auteur = models.ForeignKey(settings.AUTH_USER_MODEL, 'email')
Nom = models.CharField(max_length=70)
Prenom = models.CharField(max_length=70)
Date_de_Naissance = models.DateTimeField()
Email = models.CharField(max_length=70)
Telephone = models.CharField(max_length=15)
Reseaux = models.CharField(max_length=30)
and modec.html
<!DOCTYPE html>
{% load staticfiles %}
<link rel="stylesheet" type="text/css" href="{% static 'cv/style/style.css' %}" />
<html style="width: 100%; min-width:50%;">
<head>
<meta charset="utf-8" />
<title> Créer votre CV</title>
</head>
<body>
<header>
<table>
<tr style=" topmargin: 0px; leftmargin: 0px ">
<td style="padding: 0px; topmargin: 0px; leftmargin: 0px; width=70% ">
<img src=" {% static "cv/photos/logo.png" %}"/>
</td>
<td class="menutd">
<a style="color: #404040;" href="/cv/creer"> Enregistrer mes Informations </a>
</td>
<td class="menutd">
{% block content %}
<a style="color: #404040;" href="/cv/generer"> Generer un CV </a>
</td>
<td class="menutd">
<a style="color: #404040;" href="/login/off" align="left"> Deconnection </a>
</td>
</tr>
</table>
</header>
<div style=" width: 50%; Height: 100%; line-height: 100%; margin-top: 150px; margin-bottom: auto; margin-left: auto; margin-right: auto; vertical-align: middle; text-align: center; font-family: Helvetica Neue; font-size: 36px; color: #ffffff">
<form action="" method="POST"> {% csrf_token %}
{% for field in form %}
<input type="{{ field.Charfield }}" name="{{ field.name }}" value="{{ field.value }}"> </input><br />
{% endfor %}
<input type="submit" name="valider mon etat civil" value="Valider Article">
</form>
{% endblock %}
</div>
</div>
</body>
</html>
Where do you think I am wrong ?
Thanks in advance..
EDIT:
It appears that the form is not valid. Any idea ?
I don't know why you think you need to pass the instance's __dict__ attribute to the form when instantiating it. This is the cause of your problem, because the first parameter to a form is the data argument, and passing that makes the form bound - triggering validation, as the documentation explains in great detail.
Instead of doing that, you should do what you have correctly done in the POST block: pass the instance.
eta = Etatcivil.objects.get(id=etatcivil_id)
form = EtatCivilForm(instance=eta)
Also note you are doing some very strange things in the template (what is {{ form.CharField }} supposed to be?) but the one thing you are not doing is showing the form errors, which you should do - otherwise you won't know why the form is not valid. Again, all this is explained in great detail in the documentation.
I am trying to get through a proxy server through python to extract some information from the website, so far I this piece of code, but it doesnt seem to be working
import requests
import BeautifulSoup
URL = 'http://proxy.library.upenn.edu/login?url=http://clients1.ibisworld.com/'
session = requests.session()
# This is the form data that the page sends when logging in
login_data = {
'pennkey': "****",
'password': "****",
'submit': 'login',
}
# Authenticate
r = session.post(URL, data=login_data)
doc = BeautifulSoup.BeautifulSoup(r.content)
print doc
edit: this is what this prints:
Gorkems-MacBook-Pro:desktop gorkemyurtseven$ python extract.py
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<meta name="HandheldFriendly" content="True" />
<meta name="viewport" content="width=device-width, height=device-height, user-scalable=yes, minimum-scale=.5" />
<title>University of Pennsylvania Libraries Proxy Service - Login</title>
<link href="/public/proxysm.css" media="print, screen" rel="stylesheet" type="text/css" />
<script language="javascript">
function validate(){
var isgoldcard = document.authenticate.pass.value;
var isgoldcardRegxp = /00000/;
if (isgoldcardRegxp.test(isgoldcard) == true)
alert("Authentication is by PennKey only.");
}
</script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-982196-4']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
<!--[if IE]>
<style>
table, form .limitwidth {width: 252px;}
.holdsubmit {width: 143px;}
</style>
<![endif]-->
</head>
<body onload="document.authenticate.user.focus();">
<div id="logostripe">
<div><img src="/public/librarieslogologin.gif" border="0" alt="Penn Libraries Home" /></div>
</div>
<h1>Libraries Proxy Service</h1>
<div id="holder">
<form name="authenticate" action="https://proxy.library.upenn.edu/login" method="post" autocomplete="off">
<div class="limitwidth">
<input type="hidden" name="url" value="http://clients1.ibisworld.com/" />
<script type="text/javascript">
var t = location.search;
t = t.substr(t.indexOf('proxySessionID')+15,t.indexOf('&')-16);
document.cookie="proxySessionID="+escape(t)+"; path=/; domain=.library.upenn.edu";
</script>
<table align="center" cellspacing="0" cellpadding="2" border="0">
<tr>
<td class="holdlabels"><label for="user">PennKey:</label></td>
<td><input type="text" name="user" /></td>
</tr>
<tr>
<td><label for="password">Password:</label></td>
<td><input type="password" name="pass" onblur="validate(); return false;" /></td>
</tr>
<tr>
<td></td>
<td class="holdsubmit">
<div><input type="submit" value="Login" /></div>
</td>
</tr>
</table>
</div>
</form>
<ul class="moreinfo">
<li><a class="menuitem" href="http://www.upenn.edu/computing/pennkey">PennKey information</a></li>
</ul>
<div class="notices">
The Library Proxy Service allows you to use
domain-restricted resources & services by authenticating yourself as Penn Faculty,
Student, or Staff.
</div>
<div class="alert">
Please note limitations on the use of restricted online resources.
<br /><br />
PennKey holders must be current faculty, student, or staff, have valid University PennCommunity credentials and abide by stated Restrictions On Use.
<br /><br />
In addition, users agree to the University's Appropriate Use Policy.
</div>
</div><!-- close holder -->
</body>
</html>
Here's a solution that works for me (also using Penn's proxy server):
import requests
from bs4 import BeautifulSoup
proxies = {'https': 'https://proxy.library.upenn.edu'}
auth = requests.auth.HTTPProxyAuth('[username]', '[password]')
r = requests.get('http://www.example.com/', proxies=proxies, auth=auth)
print BeautifulSoup(r.content)
The first key is that the proxy server is https, and not http (this took me far too long to figure out). Next, you must use the requests.auth.HTTPProxyAuth method for authenticating with the server. Once, you set these two vars, however, you should be able to navigate wherever you need.