I have two input buttons. One is for uploading a file, and the other one is a submit button that adds the uploaded file to the database.
My problem is, after I submit the file, the first button that's used for uploading goes back to "No file chosen" next to the button. However, I want the uploaded file name to "stick" to the UI/html page as the file chosen.
Here is my File class:
class Files(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String, unique=True, nullable=False)
data = db.Column(db.LargeBinary)
Here is my HTML code:
<td>
<form class="" action="{{url_for('main.upload_file')}}" method="post" enctype="multipart/form-data">
<input type="hidden" name="id" value="{{row.id}}">
<input style="margin-bottom: 5px;" type="file" accept=".csv" name="csvfile" id="upload" value ="{{row.name}}"> <br>
<input style="margin-bottom: 10px;" type="submit" name="" value="Submit"> <br>
</form>
<a href={{ url_for('main.files') }}>Go to Downloads Page</a>
<br>
</td>
I've tried making the value attribute equal to the file name getting passed in ex. value ="{{row.name}}" for the file type <input> above, but that doesn't keep the file chosen name on the page after submission either. I can't find any videos or posts that deal with this problem, so I would really appreciate any guidance. TIA!
I think setting a default value for an input field of type file is forbidden for security reasons.
However, if you want to keep the name of the selected file, you can aim for a transfer with AJAX. Here you can suppress the standard behavior of the form. The page is not reloaded and the form is not reset.
The example below shows you how it works.
Flask (app.py)
from flask import Flask
from flask import (
render_template,
request,
)
app = Flask(__name__)
#app.route('/')
def index():
return render_template('index.html')
#app.route('/upload-file', methods=['POST'])
def upload_file():
if 'csvfile' in request.files:
file = request.files['csvfile']
if file.filename != '':
# handle file here!
return '', 200
return '', 400
HTML (templates/index.html)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<form name="my-form" method="post">
<input type="file" name="csvfile" />
<input type="submit" />
</form>
<script type="text/javascript">
((uri) => {
const elem = document.querySelector('form[name="my-form"]');
elem.addEventListener('submit', evt => {
evt.preventDefault();
const formData = new FormData(evt.target);
fetch(uri, {
method: 'post',
body: formData
}).then(resp => {
if (resp.status === 200) {
console.log('Submit successful.');
}
});
})
})({{ url_for('.upload_file') | tojson }});
</script>
</body>
</html>
I don't know if it is possible to default the value the file-input field shows but what you could do is just have a row above the input field showing the currently uploaded/chosen file (if there is any). So something like this:
<td>
<form class="" action="{{url_for('main.upload_file')}}" method="post" enctype="multipart/form-data">
<input type="hidden" name="id" value="{{row.id}}">
{% if row.name %}
<p>Currently chosen file: {{row.name}}</p>
<p>You can select a new file below</p>
{% endif %}
<input style="margin-bottom: 5px;" type="file" accept=".csv" name="csvfile" id="upload"> <br>
<input style="margin-bottom: 10px;" type="submit" name="" value="Submit"> <br>
</form>
<a href={{ url_for('main.files') }}>Go to Downloads Page</a>
<br>
</td>
Related
I try to create my own session middleware and my uauth system using Django. I've got the following code:
class CheckSessionsExistMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
...
response = self.get_response(request)
...
response.status_code = 401
response.reason_phrase = 'Unauthorized'
realm = 'some_app'
response['WWW-Authenticate'] = f'Basic real={realm}'
return response
When i set to respone header 'WWW-Authenticate' the string that contains word 'Basic', Django returns "internal" the sign in form and i do not understand.
Link to example of "internal" sign in form that Django returns: https://psv4.userapi.com/c235131/u2000021998/docs/d23/bc9d828c3755/file.png?extra=0qo4COrPeQh3mwjuRs1WoYsB3GVW8WB-Xn01jjtQz7muPVFWRqKjsm0itRqJFhOqjoYoKQGpAqWbG4xNQlJD3_kcs1u0UNct_76s6b1jv0u9oW76cnH2bGBTWWt_hpSQY-OpgxtRj_h56RPnwMZC73NRHw
Is there a way to disable this behavior?
Example of returning html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form id="login_form" action="http://127.0.0.1:8000/auth/register/" method="post">
<label for="username_input">
Usesrname
</label>
<input type="text" id="username_input" name=""> <br>
<label for="password_input">
Password
</label>
<input type="text" id="password_input" style="margin-left: 10px"> <br>
<input type="submit" value="Sign in">
</form>
Is it first time? Sign up
</body>
</html>
I expected that Django just return to client the header 'WWW-Authenticate' with value 'Basic realm=some_app' and my html form without "internal" sign in form.
I'm new to Python and trying to develop simple web application.
In the code below I am trying to retrieve values from DB and rending on HTML page
I'm able to see the HTML page but not values passed. Please help me here.
Python code
#app.route('/userDetails', methods=['POST', 'GET'])
def userDetails():
if request.method == 'POST':
print('in get method')
userid = request.form['userId']
print('user id ', userid)
conn = mysql.connect()
cursor = conn.cursor()
# Get User Details
print('execut sql')
result = cursor.execute("SELECT * FROM tbl_user WHERE user_id= %s", [userid])
if result > 0:
data = cursor.fetchall()
for row in data:
userId = row[0]
name = row[1]
userName = row[2]
password = row[3]
return render_template("userDetails.html", userId=userId, name=name, userName=userName, password=password)
else:
return render_template('index.html')
cursor.close()
HTML code below.
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/html">
<head>
<title>Python Flask Bucket List App</title>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<h3 class="text-muted">Python Flask App </h3>
</div>
<div class="jumbotron">
<h1>Display User Details</h1>
<div class="jumbotron">
<form class=class="form-userDetails, action="/userDetails", method="POST">
User ID:<input type="text" name="userId" class="form-control">
Name <output name="name" id="name" for="userId" class="form-control"></output>
User Name <output name="userName" id="userName" for="userId" class="form-control"></output>
Password <output name="password" id="password" for="userId" class="form-control"></output>
</br>
<button id="btnretive" class="btn btn-lg btn-primary btn-block" type="submit">Retrive</button>
</form>
</div>
<div class="Footer">
<footer class="footer">
<p>© Company 2015</p>
</footer>
</div>
</div>
</body>
</html>
#DRaj, you are using <output> tag in incorrect way. From the specification,
The HTML Output element () is a container element into which a site or app can inject the results of a calculation or the outcome of a user action.
For more info and example refer to this Mozilla page.
Now,
Flask uses Jinja2 template engine for its HTML rendering. So, the correct way to output values would be to enter a python variable inside Expression delimiters {{ ... }} in the HTML and pass the variables to render_template method.
i.e.
<form class=class="form-userDetails, action="/userDetails", method="POST">
User ID:<input type="text" name="userId" class="form-control">
Name: {{ name }}
User Name: {{ userName }}
Password: {{ password }}
</br>
<button id="btnretive" class="btn btn-lg btn-primary btn-block" type="submit">Retrive</button>
</form>
and the python code should be:-
return render_template("userDetails.html", name=name, userName=userName, password=password)
Refer to this Jinja template designer documentation for more information.
I have a Python script that uses Flask web framework to let users ask a question and depending on some certain questions, the application should ask back some questions to the user on a second webpage. The answers to the questions are evaluated based on the questions and displayed on the initial webpage.
model.py
### Importing Flask ###
from flask import Flask, render_template, request, session, redirect, url_for
### Initializing Flask ###
app = Flask(__name__)
#app.route('/')
def index():
return render_template('init.html')
#app.route('/handle_data', methods = ['POST', 'GET'])
def handle_data():
### User Inputs Question ###
userQuestion = request.form['userQuestion']
def model():
message = "Depends on User"
if message == "Depends on User":
return render_template('user_information.html', userQuestion = userQuestion)
else:
message = "Your answer is ABC."
return message
message = model()
return render_template('init.html', userQuestion = userQuestion, message = message)
#app.route('/user_information', methods = ['POST', 'GET'])
def user_information():
userLevel = request.form['userLevel']
userDOJ = request.form['userDOJ']
userType = request.form['userType']
message = "Answer for Eligibility."
return render_template('init.html', userLevel = userLevel, userDOJ = userDOJ, userType = userType, message = message)
if __name__ == '__main__':
app.run()
These are my two HTML files:
init.html (initial webpage)
<!DOCTYPE html>
<html>
<head>
<title>Human Resources</title>
<!-- for-mobile-apps -->
</head>
<body>
<div class="main">
<div class="w3_agile_main_grid">
<h2>Human Resource Portal</h2>
<br>
<p>Hi</p>
<form action="{{ url_for('handle_data') }}" method="post" class="agile_form">
<input type="text" name="userQuestion" placeholder="Ask your question..." required="">
<input type="submit" value="Submit">
</form>
<p>{{ message }}</p>
</div>
</div>
</body>
</html>
user_information.html (second webpage)
<!DOCTYPE html>
<html>
<head>
<title>Human Resources</title>
</head>
<body>
<div class="main">
<div class="w3_agile_main_grid">
<h2>Human Resource Portal</h2>
<form action="{{ url_for('user_information') }}" method="post" class="agile_form">
<!--<input type="text" name="userName" placeholder="Enter your name." required="">-->
<input type="text" name="userLevel" placeholder="What is your level?" required="">
<input type="text" name="userDOJ" placeholder="What is your date of joining?" required="">
<input type="text" name="userType" placeholder="Are you on sabbatical or specialist?" required="">
<input type="submit" value="Submit">
</form>
</div>
</div>
</body>
</html>
When I execute my script and enters a question, what I get is the HTML code for user_information.html as my answer which is not what I want.
Ouput after I click Submit:
https://ibb.co/cwhRpk
Expected output after I click Submit:
https://ibb.co/c7CFh5
https://ibb.co/dX9T25
I can get the desired output if I remove the model() construct but that will make my code inefficient because in my actual application I have to call model() multiple times with different parameters.
Can anyone please suggest me what approach should I take? I'm totally stuck in this part. Thanks, any help is appreciated!
Your nested model() function does not make any sense at all. It returns the result of render_template, which is a complete response including HTTP headers etc. If you try and insert that into another template, Jinja will be forced to try and convert it to a string, which gives the result you see.
This is not at all the way to compose templates. Jinja supports template inheritance; you should call render_template once only, using a child template that inherits from a common base.
Using Flask and SQLAlchemy on my localhost, I am looking to be able to submit a simple contact form and, using AJAX, pass the submitted data along to my Flask API and then insert it into my local database, named contact.db.
To set up my database, I put together a script named setup.py, which successfully creates a database in my working directory. Its contents look as follows:
from sqlalchemy import create_engine, ForeignKey
from sqlalchemy import Column, Date, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, backref
engine = create_engine('sqlite:///contact.db', echo=True)
Base = declarative_base()
########################################################################
class Contact(Base):
""""""
__tablename__ = "contact"
id = Column(Integer, primary_key=True)
f_name = Column(String)
l_name = Column(String)
email = Column(String)
message = Column(String)
#----------------------------------------------------------------------
def __init__(self, f_name, l_name, email, message):
""""""
self.f_name = f_name
self.l_name = l_name
self.email = email
self.message = message
# create tables
Base.metadata.create_all(engine)
My simple contact page collects the data and submits it to my flask route /contact/request using AJAX (I have confirmed this to work via the console). For reference, however, here is the code I use in contact.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Contact</title>
<!-- Bootstrap -->
<link href="{{ url_for('static', filename='css/bootstrap.min.css') }}" rel="stylesheet">
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://code.jquery.com/jquery.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="{{ url_for('static', filename='js/bootstrap.min.js') }}"></script>
<script>
$(document).ready(function(){
$("#submitForm").click(function()
{
var firstName = $("#f_name").val();
var lastName = $("#l_name").val();
var email = $("#email").val();
var mess = $("#mess").val();
var nud = {
"f_name" : firstName,
"l_name" : lastName,
"email" : email,
"message" : mess
}
$.ajax({
type: "POST",
url: "/contact/request",
data: JSON.stringify(nud, null, '\t'),
contentType: 'application/json;charset=UTF-8',
success: function(result) {
console.log(result);
}
})
});
})
</script>
</head>
<body>
<div class="row">
<div class="col-md-3"></div>
<div class="col-md-6">
<div class="panel panel-default">
<div class="panel-heading">
<h1 style="text-align: center">Contact Me</h1>
</div>
<div class="panel-body">
<form role="form">
<div class="form-horizontal" class="form-group" style="width:50%">
<label for="name has-success">First Name</label>
<input class="form-control input-md" type="text" class="form-control" id="f_name" placeholder="Matthew">
</div><br />
<div class="form-horizontal" class="form-group" style="width:50%">
<label for="email">Last Name</label>
<input class="form-control input-md" type="text" class="form-control" id="l_name" placeholder="Gross">
</div><br />
<div class="form-horizontal" class="form-group" style="width:50%">
<label for="email">Email</label>
<input class="form-control input-md" type="email" class="form-control" id="email" placeholder="mattkgross#gmail.com">
</div><br />
<div class="form-group">
<label for="aboutMe">Message</label>
<textarea class="form-control" id="mess" placeholder="What's up?" rows="3" ></textarea>
</div>
<div>
<button type="button" input type "submit" class="btn btn-success" id="submitForm">Submit</button>
</div>
</form>
</div>
</div>
</div>
<div class="col-md-3"></div>
</div>
</body>
</html>
Finally, I have my actual Flask API script that I run in order to start up my service on localhost. The /contact route works fine. However, when I send the data via my form submission, I get an internal server error. This is undoubtedly being caused by my incorrect attempt at inserting the parsed JSON into my contact database. Below is the code used in my api.py:
from flask import Flask
from flask import request
from flask import render_template
import datetime
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from setup import Contact
app = Flask(__name__)
#app.route('/contact')
def contact():
return render_template('contact.html')
#app.route('/contact/request', methods=["POST"])
def contact_request():
if request.method == "POST":
engine = create_engine('sqlite:///contact.db', echo=True)
# Create a Session
Session = sessionmaker(bind=engine)
session = Session()
new_contact = Contact(request.json['f_name'],
request.json['l_name'],
request.json['email'],
request.json['message'])
# Add the record to the session object
session.add(new_contact)
# commit the record the database
session.commit()
#return str(request.json)
app.debug = True
app.run()
If I comment out the two lines:
session.add(new_contact)
session.commit()
and replace them with return str(request.json), my console successfully returns the JSON I sent. I am just completely lost as to where I am going wrong in inserting my data into the database and why it is throwing an error at me for my attempt.
Any help you can give me would be very much appreciated - hopefully it's something simple I overlooked in being new to this whole thing. Thanks!
In flask you have to return something for your route otherwise it will lead to odd behavior. In your case you could return something as simple as an "OK" to let your AJAX know the function completed successfully.
I'm trying to implement a system of uploading a file (image) to the server running pyramid. Right now, this code gives me an AttributeError: 'unicode' object has no attribute 'file' exception:
Server-side:
session = Session()
username = authenticated_userid(request)
if username == None:
return HTTPNotFound()
else:
user = session.query(User).filter(User.username == username).first()
if 'photo.submitted' in request.params:
input_file = request.POST['file_input'].file
tmp = '../static/images/%s' % (session.query(ProfilePic).order_by(-ProfilePic.photo_id).first().photo_id + 1)
open(tmp, 'w').write(input_file.read())
tmp.close()
return Response('OK')
return {}
HTML:
<html>
<body>
<form action="/settings" method="post">
<input type="file" name="file_input" value="Choose image" />
<p><input type="submit" name="photo.submitted" value="Save" /></p>
</form>
</body>
</html>
Something that seems simple, but won't work. I was trying to follow this tutorial, but it seems it only works with video/audio files. How could I make this work?
For file uploads, you need to alter the form enctype to use multipart/form-data:
<html>
<body>
<form action="/settings" method="post" enctype="multipart/form-data">
<input type="file" name="file_input" value="Choose image" />
<p><input type="submit" name="photo.submitted" value="Save" /></p>
</form>
</body>
</html>