Flask how to make html page show up? - python

Okay so I will just have some reading to do. I don't expect anyone to answer anymore. Thanks for everybody that took the effort to reply.
I have followed the following guide to create a simple python app: https://guillaumegenthial.github.io/serving.html
edit:
Okay retrospectively I should have read more stuff before asking this question. Let me try to rephrase what I am trying to do.
I am trying to access the below defined html page. There I want to input text in a textbox and then process that text in the api function defined in flask. The results I then want to output inside the html page.
I tried to find some more ressources on this, but I am new to html and flask and am struggeling.
Any tips would be appriciated.
My app.py file:
from flask import Flask, request, jsonify
from flask_cors import CORS
from serve import get_model_api
app2 = Flask(__name__)
CORS(app2) # needed for cross-domain requests, allow everything by default
model_api = get_model_api()
# default route
#app2.route('/')
def index():
return "Index API"
# HTTP Errors handlers
#app2.errorhandler(404)
def url_error(e):
return """
Wrong URL!
<pre>{}</pre>""".format(e), 404
#app2.errorhandler(500)
def server_error(e):
return """
An internal error occurred: <pre>{}</pre>
See logs for full stacktrace.
""".format(e), 500
# API route
#app2.route('/api', methods=['POST'])
def api():
input_data = request.json
output_data = model_api(input_data)
response = jsonify(output_data)
return response
if __name__ == '__main__':
app2.run(host='0.0.0.0', port=81, debug=True)
The html file:
<body>
<div class="container col-lg-6">
<div style="padding-bottom: 0.5cm">
<div class="card text-center bg-light">
<div class="card-body" style="padding-bottom: 0.2cm">
<input class="card-title form-control" type="text" id="input" name="input" placeholder="Input sentence"/>
<button class="card-text btn btn-outline-primary" id="btn">Find Entities</button>
<button class="card-text btn btn-outline-primary" id="btn2">Get random Tweet</button>
<div class="spinner" id="spinner" style="display: none">
<div class="double-bounce1"></div>
<div class="double-bounce2"></div>
</div>
</div>
<div class="card-footer bg-white">
<pre class="card-text api-pre" style="padding-bottom: 0.2cm">
<div class="item" id="api_input">Nur der HSV </div>
<div class="item" id="api_output">0 0 B-ORG</div>
</pre>
</div>
</div>
</div>
</div>
</body>
<script type="text/javascript">
function api_call(input) {
// hide button and make the spinner appear
$('#btn').toggle();
$('#spinner').toggle();
$.ajax({
url: "0.0.0.0:81/api",
method: 'POST',
contentType: 'application/json',
data: JSON.stringify(input),
success: function( data, textStatus, jQxhr ){
// toggle the spinner and button
$('#btn').toggle();
$('#spinner').toggle();
// fill the html for answer
$('#api_input').html( data.input );
$('#api_output').html( data.output );
$("#input").val("");
},
error: function( jqXhr, textStatus, errorThrown ){
$('#btn').toggle();
$('#spinner').toggle();
$('#api_input').html( "Sorry, the server is asleep..." );
$('#api_output').html( "Try again in a moment!" );
console.log( errorThrown );
},
timeout: 3000 // sets timeout to 10 seconds
});
}
$( document ).ready(function() {
// request when clicking on the button
$('#btn').click(function() {
// get the input data
var input = $("#input").val();
api_call(input);
input = "";
});
});
</script>

By adding /api you are only making a GET request and that is all that is defined:
#app2.route('/api', methods=['POST'])
def api():
input_data = request.json
output_data = model_api(input_data)
response = jsonify(output_data)
return response
If you want the information available for testing, you can just add the GET method like so:
#app2.route('/api', methods=['GET', 'POST'])
However, I think you may want to read up on HTML request methods to see what is the most appropriate type for what you are making the endpoint do.
I'm guessing the tutorial information is expecting a POST for the api, which is common. A simple example of a POST request can be done from most commandline with curl:
curl -X POST MYIP/api -d "{ \"myKey\": \"myValue\"}"
This should return whatever response that is given by the api method.

Related

No return of result from FLASK call via AJAX in an alert notifcation on the web page

Basically I a comparing two texts one input is a pdf, another basic text.
I have created index html and within is another html for a bit clarity. using python FLASK feature.
All the code runs separately, all mentioned errors for invalid input run very fine together, its just the main result output, I presume I am messing up somehow in calling and executing the main function because all the alerts and file checks are working , and the logic inside of flask is working too.
My html file with ajax and form :
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
function submitForm() {
// Show the loading screen
document.getElementById("loading").style.display = "block";
// Get the input values
var JD = document.getElementById("JD").value;
var file = document.getElementById("FL").file[0];
// Check if a file has been selected and is a pdf
if (!file || file.type !== 'application/pdf') {
alert("Please select a valid PDF file");
return;
}
// Check if file size is less than 5 MB
if (file.size > 5000000) {
alert("File size should not exceed 5 MB");
return;
}
// Create a FormData object to send both the file and the jd to the API
var formData = new FormData($('#upload_form')[0]);
formData.append("FL", FL);
formData.append("JD", JD);
// Make the API call
$.ajax({
url: base_url + "api/Analyze",
type: "POST",
data: formData,
processData: false,
contentType: false,
success: function(result) {
// Hide the loading screen
document.getElementById("loading").style.display = "none";
alert(result);
},
error: function () {
// Hide the loading screen
document.getElementById("loading").style.display = "none";
// Display the error
alert("Error during API call");
}
});
}
</script>
</head>
<body>
<h2>Analysis</h2>
<form id="upload_form" enctype="multipart/form-data">
<p>
<label for="JD">Description:</label>
<textarea name = "JD" id="JD" rows="4" cols="50"></textarea>
</p>
<p>
<label for="FL">FILE:</label>
<input type="file" name="FL" id="FL" accept="application/pdf">
</p>
<p>
<input type="button" value="Submit" onclick="submitForm()">
</p>
</form>
<div id="loading" style="display: none;">Loading...</div>
And this is the app.py flask file -
from flask import Flask, render_template, redirect, request, jsonify
import fitz
import re
import sys
#(please ignore irrelevant imports)
app = Flask(__name__)
#app.route('/', methods=['GET'])
def index():
return render_template('index.html')
#app.route('/Analyze', methods=['GET'])
def analyze():
return render_template('analyze.html')
#(ignore this bulk one)
#app.route('/BulkAnalyze', methods=['GET'])
def bulk_analyze():
return render_template('Bulk.html')
#app.route('/api/Analyze', methods=['POST'])
def Submit():
pdf_file = request.files['FL']
jd_text = request.form['JD']
jd_text = " ".join(jd_text.split('\n'))
with fitz.open(pdf_file) as doc:
text = ''
for page in doc:
text += page.get_text()
text = ' '.join(text.split('\n'))
# Perform text comparison
matching_words = [word for word in jd_text.split() if word in text.split()]
match = 100 * len(matching_words) / len(jd_text.split())
return jsonify({'result': 'The matching percentage is :' + match })
if __name__ == "__main__":
app.run()
I was trying to compare those two text input to get a percentage output as an alert.
I am aware i could display output on page or another webpage to circumnavigate this issue, but this is not some irl problem and i would love to learn from this.
An uploaded file results in an object of type FileStorage on the server side. It is a file-like object for the loaded PDF file. It is not possible to extract the text directly from the FileStorage object. The data must first be read into a stream.
The following is the slightly modified example based on your code.
from flask import (
Flask,
jsonify,
redirect,
render_template,
request
)
import fitz
import io
import re
app = Flask(__name__)
#app.route('/')
def index():
return render_template('index.html')
#app.post('/api/analyze')
def api_analyze():
pcnt = 0
try:
desc = request.form['desc']
file = request.files['file']
with io.BytesIO(file.read()) as fh, fitz.open(stream=fh, filetype='pdf') as doc:
text = ' '.join(page.get_text() for page in doc)
tokens_desc = set(re.findall(r'\b\w+\b', desc))
tokens_text = set(re.findall(r'\b\w+\b', text))
tokens_match = tokens_text & tokens_desc
pcnt = len(tokens_match) / len(tokens_desc) * 100
finally:
return jsonify(result=f'The matching percentage is: {pcnt}%')
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Index</title>
</head>
<body>
<form name="upload-form">
<div>
<label for="file">Choose a file:</label>
<input type="file" name="file" id="file" accept="application/pdf" />
</div>
<div>
<label for="desc">Description:</label>
<textarea name="desc" id="desc" rows="4" cols="50"></textarea>
</div>
<div>
<input type="submit" value="Submit" />
</div>
</form>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
$(function() {
$('form[name="upload-form"]').submit(function(event) {
event.preventDefault();
const file = this['file'].files[0];
if (!file || file.type !== 'application/pdf') {
alert('Please select a valid PDF file');
return;
}
if (file.size > 5000000) {
alert('File size should not exceed 5 MB');
return;
}
$.ajax({
url: '/api/analyze',
type: 'post',
data: new FormData(this),
processData: false,
contentType: false
}).done(function(data) {
alert(data.result);
}).fail(function() {
alert('Error during API call.');
});
})
});
</script>
</body>
</html>

I am getting a `KeyError` when I receive a request to my API

I am building a dictionary app with Flask where users can add new words, I am trying to request the word from the word input , I am having issues with the POST request, the error I am receiving on my terminal is this:
line 50, in add_word
word = req['word']
keyError:'word'
and this is how I wrote the code in my app.py file:
#app.route('/word', methods= ['POST'])
def add_word():
req = request.get_json()
word = req['word']
meaning = req['meaning']
conn = mysql.get_db()
cur = conn.cursor()
cur.execute('insert into word(word, meaning) VALUES (%s, %s)',(word, meaning))
conn.commit()
cur.close()
return json.dumps("success")
here is the json in my JavaScript file, I am posting to my flask app:
$('#word-form').submit(function() {
let word = $('word').val();
let meaning = $('meaning').val();
$.ajax({
url: '/word',
type: 'POST',
dataType: 'json',
data : JSON.stringify({
'word': word,
'meaning': meaning
}),
contentType: 'application/json, charset = UTF-8',
success: function(data) {
location.reload();
},
error: function(err) {
console.log(err);
}
})
here is the Html page:
<div class="div col-md-2 sidenav">
All words
Add New
<div>
<form action="javascript:0" id="word-form">
<div class="form-group">
<label for="word">Word:</label>
<input type="text"
class="form-control"
name="word"
id="word"
placeholder="Type in the word here:"
required>
</div>
<div class="form-group">
<label for="Meaning">Meaning:</label>
<textarea class="form-control" id="meaning"
placeholder="enter the meaning here: " required></textarea>
</div>
<button type="submit" class="btn btn-primary btn-block btn-lg" id="submit">Submit</button>
<button type="button" class="btn btn-warning btn-block btn-lg" id="cancel">Cancel</button>
</form>
</div>
</div>
<div class="div col-md-10 main">
<table style="border: 2px;">
<thead>
<tr>
<th>SN</th>
<th>Word</th>
<th>Meaning</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
{% for word in words %}
<tr>
<td>{{ loop.index }}</td>
<td>{{ word['word'] }}</td>
<td>{{ word['meaning'] }}</td>
<td><button class="btn btn-sm btn-success btn-block edit" id="{{word['id']}}">Edit</button></td>
<td><button class="btn btn-sm btn-danger btn-block delete" id="{{word['id']}}">Delete</button></td>
</tr>
{% else %}
<tr>
<td colspan="3">The dictionary has no words at the moment, please come bay later</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
Things seem to be in a confused state in the client code, and potentially the application architecture in general.
There are two general approaches to designing web apps that impacts how you create routes and build requests. One approach is the AJAX-based single page app architecture that loads one HTML skeleton, then uses JS (jQuery here) to make AJAX requests to a JSON API and injects the response data into the page using JS instead of page refreshes and navigations. Since you don't have a client-side router, this doesn't qualify as a SPA, but it's worth understanding to provide context on your design.
On the other hand, you can use HTML form submissions (<form action="/path/to/resource" method="POST">) and render_template to display new pages with a browser refresh for all form submissions.
The code here is somewhere in the middle, which is potentially fine (you can use AJAX for certain events and form submissions but mostly rely on full-navigation templates for routes). But it's important to be clear on the request-response workflow you're adopting so the design makes sense and can be debugged.
Here are few oddities/inconsistencies in your current design:
return json.dumps("success") is not really JSON as it seems like you want it to be--use jsonify and a dictionary or list, e.g. jsonify({"status": "success"}; it's customary for JSON routes to return JSON responses if they aren't rendering templates or redirecting.
The client ignores the JSON response and calls location.reload. If you're just planning on reloading and you have no special client processing to do, there's not much point in using AJAX or JSON here--just submit the form to the backend and redirect to the template or static HTML page you want to show next. No client-side JS involved. Redirect to an error page or render a template with errors shown on the form on error.
Links with href="#" are poor practice. Better to use buttons if you're adding JS to these handlers and you don't want them to trigger navigation. This is semantically more appropriate and doesn't hijack the URL.
<form action="javascript:0" id="word-form"> looks like it's trying to prevent the form submission, but all this does is replace the page content with the character "0". I can't imagine how this is useful or desirable. Submitting a form to a JSON route can produce the error you're seeing--another sign of confusion about which architecture you're following. Use event.preventDefault() (add the event parameter to the callback to .submit()) to prevent the form submission from refreshing the page.
After you've prevented the page refresh, you can debug the AJAX request.
When a route is complaining about missing keys, consider that objects with keys pointing to undefined disappear when serialized as JSON (undefined is not a thing in JSON):
const word = undefined;
const foo = 42;
const bar = "baz";
console.log({word, foo, bar}); /* =>
{
"word": undefined,
"foo": 42,
"bar": "baz"
}
*/
console.log(JSON.stringify({
word,
foo,
bar,
})); // => {"foo":42,"bar":"baz"}
If you add a console.log to see if your values are there (or print the JSON on the backend route before indexing into it), these values aren't defined:
let word = $('word').val();
let meaning = $('meaning').val();
console.log(word, meaning); // <-- undefined, undefined
Why? The reason is that these selectors are missing the # symbol prefix to denote an id. Without it, jQuery looks for <word></word> and <meaning></meaning> HTML elements that don't exist.
Change these lines to:
const word = $('#word').val();
const meaning = $('#meaning').val();
and now your request body should be ready to send.
Next problem: $.ajax's dataType key specifies the response type, not the request type. Use dataType: "json" to specify the appropriate request header to trigger the Flask handler to JSON parse the request body.
After these changes, things should work, with the caveat that it might be time for a rethink of your overall design, or at least a redesign of this route workflow.
A word of advice: work slowly and test all of your assuptions at each step. The code here shows many errors that are hard to debug because they're stacked on top of each other. Isolate and validate each behavior in your app. For example, when adding the jQuery submit handler and collecting the form values, print them to make sure they're actually there as you expected.
In case you're stuck, here's minimal, complete, runnable code you can reference.
app.py:
from flask import (
Flask, jsonify, render_template, request, url_for
)
app = Flask(__name__)
#app.route("/")
def index():
return render_template("index.html")
#app.post("/words/")
def words():
payload = request.get_json()
word = payload.get("word")
meaning = payload.get("meaning")
if word is None or meaning is None:
return (jsonify({
"error": "missing required keys `word` or `meaning`"
}), 400)
# handle db operation and report failure as above
return jsonify({"status": "success"})
if __name__ == "__main__":
app.run(debug=True)
templates/index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
</head>
<body>
<form id="word-form">
<div>
<label for="word">Word:</label>
<input
name="word"
id="word"
placeholder="Type in the word here:"
required
>
</div>
<div>
<label for="meaning">Meaning:</label>
<textarea
name="meaning"
id="meaning"
placeholder="enter the meaning here: "
required
></textarea>
</div>
<button type="submit">Submit</button>
</form>
<script>
$('#word-form').submit(function (e) {
e.preventDefault();
const word = $('#word').val();
const meaning = $('#meaning').val();
console.log(word, meaning);
$.ajax({
url: "{{url_for('words')}}",
type: "POST",
dataType: "json",
contentType: "application/json",
data: JSON.stringify({word, meaning}),
success: function (data) {
console.log(data);
},
error: function (err) {
console.error(err);
}
});
});
</script>
</body>
</html>
See also: How to get POSTed JSON in Flask?
Here are a few additional notes that are somewhat tangential to the main issue but have to be mentioned.
You have <label for="Meaning"> but no name="meaning" element to shift focus to when clicked.
It's another antipattern to put ids on everything promiscuously. Only add ids to elements when they must have one because you're using it for something specific. Prefer classes, especially for styling.
On the backend, the code here is unsafe:
req = request.get_json()
word = req['word']
meaning = req['meaning']
If your client gives a bad request with missing values, you should detect that and return a 400/422 response (or similar) rather than crashing.
For example (from the above code snippet):
req = request.get_json()
word = req.get("word")
meaning = req.get("meaning")
if word is None or meaning is None:
return (jsonify({
"error": "missing required keys `word` or `meaning`"
}), 400)
Similarly, don't assume the database operation will succeed. Always check for errors and return an appropriate response to the client.
Resources are usually plural, not singular: words, users, posts.

Reloading Variable Value when the value is updated from Server (FLASK, HTML, JQUERY)

I am very new to python and am starting to learn about using AJAX and Jquery.
I'm going to try to formulate my problem clearly but if it's in any way unclear, please tell me so and I will try to improve it.
I have a web app which is run from the function userinterface.py, and userinterface.py should be run from the function central.py.
In central.py, there is a variable called "devicequantity", which should be assigned to a div element in the html. I tried using ajax request for this (devicequantity is a changing variable).
In my web app, there are some fields that are hidden depending on the value of devicequantity. How can I assign devicequantity to the web app and let it update whenever a new value is assigned via central.py? Thank you so much for any feedback and help!
Here are my codes:
html
<div class="col-sm-4 d-inline-flex justify-content-center align-items-center my-0">
Device quantity:
<div class="border col-sm-5 px-2 py-2 justify-content-center align-items-center" type="number" id="devicequantity" name="devicequantity"> {{ devicequantity }} </div>
</div>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script>
$(document).ready(function(){
$.ajax({
url:"/getdevicequantity",
type: "get",
success: function(response){
$("#devicequantity").html(response.devicequantity);
}
});
$('#alertsettings').hide(); $('#alertfillfield').hide(); $("#device1").hide(); $("#device2").hide(); $("#device3").hide(); $("#device4").hide(); $("#device5").hide(); $("#device6").hide(); $("#device7").hide(); $("#device8").hide(); $("#device9").hide();$("#device10").hide(); $("#SubmitSecondPart").hide(); $("#alertquantity").show();
if ($("#devicequantity").val() == 1) {$("#alertquantity").hide(); $("#device1").show(); $("#SubmitSecondPart").show();
}
else if ($("#devicequantity").val() == 2) {$("#alertquantity").hide(); $("#device1").show(); $("#device2").show(); $("#SubmitSecondPart").show();
}
else if ($("#devicequantity").val() == 3) {$("#alertquantity").hide(); $("#device1").show(); $("#device2").show(); $("#device3").show(); $("#SubmitSecondPart").show();
}
});
</script>
</script>
userinterface.py
#app.route("/", methods=['GET', 'POST'])
def home():
if request.method == 'POST':
getInputsSettings()
getInputsLicenses()
return render_template('printerlabel.html', devicequantity=devicequantity)
#app.route("/getdevicequantity")
def getdevicequantity():
return jsonify({'devicequantity' : devicequantity})
def runuserinterface():
app.run()
if __name__ == "__main__":
app.run()
central.py
devicequantity = 10
if __name__ == "__main__":
userinterface.devicequantity=devicequantity
userinterface.runuserinterface()
Your AJAX success callback function has a response parameter that you need to use.
It supposed to look like this:
success: function(response){
$("#devicequantity").html(response.devicequantity);
}
For debugging purpose you can try
success: function(response){
console.log(response);
}

Why is my POST not working after getting values

So I am getting user input from a template that uses css and jQuery, then I'm posting that data back supposedly on click. However, I am not able to access the data as I believe it is not being posted back.
I believe my ajax code is not recognizing the click, can someone please help me out. I spent the whole day trying to figure out what am I doing wrong.
#This is main code
from bottle import run, route, request, template, static_file, post
def main():
#This is main code
#route('/assets/<filepath:path>')
def server_static(filepath):
return static_file(filepath, root='./Gui/assets')
#route('/')
def home():
return template('indexTest')
#post('/home')
def home():
radius=request.forms['radius']
noTr=request.forms['noOdTurbines']
result=radius+noTr
return ({'result': result})
if __name__ == '__main__':
main()
run(host='localhost', port=8080, debug=True)
this is jQuery code
<!DOCTYPE html>
<html>
<head>
<title>AJAX Example</title>
<script type="text/javascript">
$(document).ready(function(){
$('form').on('submit',(function(event){
$.ajax({
type: "POST",
url: "/home"
data: {
radius: $('#radius').val(),
noOfTurbines: $('#noOfTurbines').val()
},
error:function(){
alert('Error: something is wrong with values!!')
}
})
event.preventDefault();
});
}));
</script>
</head>
<body>
<form method="POST" action="/home">
<div id="exampleAccount" role="tabpanel">
<div id="exampleAccountForm">
</div>
<div>
<label for="radius">Radius of Swept-Area of Wind turbine:
</label>
<input type="text" id="radius" required>
</div>
<div >
<label for="noOfTurbines">Number of Wind turbines: </label>
<input type="text" id="noOfTurbines" required>
</div>
</div>
</div>
<div >
<button type="submit" class="btn btn-default"
id="submit">Finish</button>
</div>
</form>
</body>
</html>
I have problems with the request.forms type of multidict, so I convert to dict and this solves all my problems. I usually merge the post and string URL objects into one just to make it more flexible.
def merge_dicts(*args):
result = {}
for dictionary in args:
result.update(dictionary)
return result
payload = merge_dicts(dict(request.forms), dict(request.query.decode()))
Just remember, that bottle uses the name not the id of the form element in a post. So make sure all inputs have a name.
(Which I do not see in your example)

python autofill form in a webpage

I am trying to fill a form in a webpage that has a single text box and a send button the html looks like this
<form class="form-horizontal">
<div class="row">
<div class="col-md-12">
<div id="TextContainer" class="textarea-container">
<textarea id="Text" rows="5" maxlength="700" class="form-control remove-border" style="background:none;"></textarea>
</div><button id="Send" class="btn btn-primary-outline" type="button" onclick="SendMessage()" style="margin-top:10px" data-loading-text="Loading..."><span class="icon icon-pencil"></span> Send</button>
</div>
</div>
</form>
I tried to use mechanize to submit the form with this code
import re
from mechanize import Browser
br = Browser()
response=br.open("https://abcd.com/")
for f in br.forms():
if f.attrs['class'] == 'form-horizontal':
br.form = f
text = br.form.find_control(id="Text")
text.value = "something"
br.submit()
The code runs without an error, but no submission is happening , how do I do it?
Here is the SendMessage function
function SendMessage() {
var text = $('#Text').val();
var userId = $('#RecipientId').val();
if (text.trim() === "")
{
$('#TextContainer').css('border-color', 'red');
}
else if (new RegExp("([a-zA-Z0-9]+://)?([a-zA-Z0-9_]+:[a-zA-Z0-9_]+#)?([a-zA-Z0-9.-]+\\.[A-Za-z]{2,4})(:[0-9]+)?(/.*)?").test(text))
{
$('#TextContainer').css('border-color', 'red');
$('#message').html("Links are not allowed in messages");
}
else
{
$('#Send').button('loading');
$.ajax(
{
url: '/Messages/SendMessage',
type: 'POST',
cache: false,
data:
{
__RequestVerificationToken: $('<input name="__RequestVerificationToken" type="hidden" value="CfDJ8MQSRebrM95Pv2f7WNJmKQWGnVR66zie_VVqFsquOCZLDuYRRBPP1yzk_755VDntlD3u0L3P-YYR0-Aqqh1qIjd09HrBg8GNiN_AU48MMlrOtUKDyJyYCJrD918coQPG0dmgkLR3W85gV6P4zObdEMw" />').attr('value'),
userId: userId,
text: text
}
});
}
}
I suspect the issue is that the submit button in the HTML form is not of type=submit - so mechanise won't know what to do when you call br.submit(). The fix is to either change the button type on the HTML website, or tell Browser which button to use for submitting the form:
br.submit(type='button', id='Send')
The submit method takes the same arguments as the HTML Forms API, so I recommend taking a look at the documentation for more details.
Update
The problem here seems to be the JavaScript method attached to the button. Mechanize does not support calling JavaScript functions, hence you won't be able to just use the .submit() method to submit the form. Instead, the best option would probably be to read in the SendMessage() JavaScript function, which gets called if someone clicks on the Send button, and translate it to Python manually. In the best case it consists of a simple AJAX POST request which is very easy to implement in Python. Please look here for a related question.
Second Update
Given the new information in your question, in particular the JavaScript function, you can now manually implement the POST request inside your Python script. I suggest the use of the Requests module which will make the implementation much easier.
import requests
data = {
"__RequestVerificationToken": "CfDJ8MQSRebrM95Pv2f7WNJmKQWGnVR66zie_VVqFsquOCZLDuYRRBPP1yzk_755VDntlD3u0L3P-YYR0-Aqqh1qIjd09HrBg8GNiN_AU48MMlrOtUKDyJyYCJrD918coQPG0dmgkLR3W85gV6P4zObdEMw",
"userId": "something",
"text": "something else"
}
response = requests.post("https://example.com/Messages/SendMessage", data=data)
response will now consist of the response which you can use to check if the request was successfully made. Please note that you might need to read out the __RequestVerificationToken with mechanize as I suspect it is generated each time you open the website. You could just read out the HTML source with html_source = br.read() and then search for __RequestVerificationToken and try to extract the corresponding value.
You can give name attribute to your text area like:
<form class="form-horizontal">
<div class="row">
<div class="col-md-12">
<div id="TextContainer" class="textarea-container">
<textarea id="Text" name="sometext" rows="5" maxlength="700" class="form-control remove-border" style="background:none;"></textarea>
</div><button id="Send" class="btn btn-primary-outline" type="button" onclick="SendMessage()" style="margin-top:10px" data-loading-text="Loading..."><span class="icon icon-pencil"></span> Send</button>
</div>
</div>
</form>
Then try this out:
import re
from mechanize import Browser
br = mechanize.Browser()
br.open("https://abcd.com/")
br.select_form(nr=0) #in case of just single form you can select form passing nr=0
br["sometext"] = "something"
response = br.submit()
print(response.read())
If it successfully submits form then you can read your response body.

Categories

Resources