I am attempting to take what a user highlights in order to process it for a query of a database. While I seem to be able to successfully get what is being highlighted, it seems that passing that information through to the actual database query isn't happening. There aren't any error messages. I hope there is a typo somewhere and it is an easy fix, in any scenario an extra set of eyes from a more experienced person would be greatly appreciated. I am using Python Flask to develop a web app for personal use, here is the code
{% block content %}
<head>
<style>
div.sticky {
position: -webkit-sticky;
position: sticky;
top: 0;
float: right;
width: 30%;
}
</style>
</head>
<h2 style="text-align: center;">{{ name }}</h2>
<div class="sticky" id="sticky_display">
<button type="button" onclick ="getSelectedText()" style="background: darkblue; color: white;">Query Database</button>
<form name="testform">
<textarea id="selectedtext">
</textarea>
</form>
</div>
<div class="row">
<div class="col-xs-8 col-sm-8 col-md-8 col-lg-8" style="white-space: pre-line;" id="text_display">
{{ text }}
</div>
</div>
<script>
function getSelectedText() {
var selectedText = '';
if (window.getSelection) {
selectedText = window.getSelection();
}
// document.getSelection
else if (document.getSelection) {
selectedText = document.getSelection();
}
// document.selection
else if (document.selection) {
selectedText = document.selection.createRange().text;
} else return;
function(selectedText) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function(){
if (this.readyState == 4 && this.status == 200) {
document.getElementById('selectedtext').value = this.responseText;
}
xhttp.open("POST", "/query_database', true);
xhttp.send(selectedText);
}
}
</script>
{% endblock %}
By default, POST will send
Content-Type: application/x-www-form-urlencoded
which requires that send a URL-encoded form. It appears that you're sending plain text, which would require adding
xhttp.setRequestHeader('Content-Type', 'text/plain');
before the .send()
Related
i need to create source, delete it and update as well, butting getting the same error again and again.
//component.html
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<div class="container mt-5">
<div class="form-group">
<input
type="text"
class="form-control"
placeholder="Search..."
[(ngModel)]="filterTerm"
/>
</div>
<ol>
<li *ngFor="let source of sources$ | async | filter: filterTerm">
<div class="card">
<div class="card-body">
<h5 class="card-title">{{source.name}}</h5>
<p>URL:- <a href ='{{source.url}}'>{{source.url}}</a></p>
<a class="btn btn-primary" href='fetch/{{source.id}}' role="button" style="margin-left:5px ">Fetch</a>
<button class="btn btn-primary" (click)="deleteSource(source.id)" style="margin-left:5px">Delete </button>
<button class="btn btn-primary" (click)="editSource(source.id, source)" style="margin-left:5px ">Edit </button>
<br>
</div>
</div>
</li>
</ol>
</div>
//service.ts
export class SourcesService {
API_URL = 'http://127.0.0.1:8000/sourceapi/';
constructor(private http: HttpClient) { }
/** GET sources from the server */
Sources() : Observable<sources[]> {
return this.http.get<sources[]>(this.API_URL,);
}
/** POST: add a new source to the server */
addSource(source : sources[]): Observable<sources[]>{
return this.http.post<sources[]> (this.API_URL, source);
//console.log(user);
}
deleteSource(id: string): Observable<number>{
return this.http.delete<number>(this.API_URL +id);
}
// component.ts
export class SourcesComponent implements OnInit {
filterTerm!: string;
sources$ !: Observable<sources[]>;
// deletedSource !: sources;
constructor(private sourcesService: SourcesService) { }
// prepareDeleteSource(deleteSource: sources){
// this.deletedSource = deleteSource;
// }
ngOnInit(): void {
this.Source();
}
Source(){
this.sources$ = this.sourcesService.Sources()
}
deleteSource(id : string){
console.log(id)
this.sourcesService.deleteSource(id).subscribe();
}
I tried, providing the header and also tried the steps got in the question I asked yesterday but problem did not solved till now..
Steps I tried :- "detail": "CSRF Failed: CCSRF token missing." when sending post data from angular 13 to django connected database
I am trying to write a small web application using Flask. But I have a question while creating selection list. For example, there are 2 selection lists in the web. The first one is "keyID" and second one is "fieldName". When user clicked an item in selection list "keyID" then a corresponding selection list "fieldName" appears.
Here's the HTML:
<div class="control">
<label for="keyid">KeyID of parking spots:</label><br>
<select name ="keyidList" id="keyid_list" style="width: 400px">
{% for keyid in keyIDs %}
<option value ="{{keyid}}">{{keyid}}</option>
{% endfor %}
</select><br><br>
</div>
<div class="control">
<label for="fieldname">FieldName of parking spots:</label><br>
<select name ="fieldnameList" id="fieldname_list" style="width: 400px">
{% for fieldname in fieldnames %}
<option value ="{{fieldname}}">{{fieldname}}</option>
{% endfor %}
</select><br><br>
</div>
Javascript code in HTML file
<head>
<meta charset="utf-8">
<script>
$(function(){
var select_keyid = $('#keyid_list');
var selected_keyid = select_keyid.val();
select_keyid.on('change', function(){
$.ajax({
type: 'POST',
data: JSON.stringify({
'selected_keyid': selected_keyid,
}),
url: "{{ url_for('auth.get_fieldname_list') }}",
success: function(data) {
$("#fieldname").empty();
for (var i = 0; i < data.length; i++) {
$("#fieldname").append('<option value="' +fieldname+ '">' + fieldname + '</option>');
}
}
});
});
});
</script>
</head>
And here's the Python Flask code
#auth.route('/get_fieldname_list', methods=['POST'])
def get_fieldname_list():
req = request.json
keyid = req.get('selected_keyid')
fieldname = get_field_name_from_keyid(keyid)
return fieldname
I personally think that, the problem is with ajax code but I don't know why and how to fix it. Any advice will be really appreciated.
This question already has answers here:
Display data streamed from a Flask view as it updates
(3 answers)
Closed 2 years ago.
I'm running a bot and I'm trying to output the bot's logs to a simple webpage as a stream of HTML content (each log is sent as <p>{log}</p>). If I output the stream to route "/log_stream" and then go to that route, I can see the logs and they update and everything works as expected. However, I can't figure out how to incorporate that stream in another webpage. I tried embedding it using an <iframe> with the "/log_stream" route as the src but then the iframe wouldn't render at all. Any idea how to make this work?
NOTE: Please don't mark this as a duplicate of Display data streamed from a Flask view as it updates The answer there is either outdated or incorrect. Although you can't update the template directly after it's been rendered on the server, you definitely can embed dynamic content in that template using an iframe or img, like in this tutorial where he uses an image dynamically to create a video stream. Not being able to dynamically update the template itself is NOT the same thing as not being able to dynamically update the content IN that template.
app.py:
from flask import Flask, render_template
from threading import Thread
from bot import Bot
from logger import Logger
from config import config
application = Flask(__name__)
logger = Logger()
#application.route('/')
def index():
return render_template('index.html.jinja', products=config['targets'], status='running')
#application.route('/log_stream')
def log_stream():
return logger.printerStream()
if __name__ == '__main__':
bot = Bot(logger)
botThread = Thread(target=bot.run)
botThread.start()
application.run(host='0.0.0.0', debug=True)
logger.py (relevant parts):
def getLogHTML(self, logObj):
if logObj['type'] == INFO:
return "<p style=\"color:green\">"+logObj['text']+"</p>\n"
if logObj['type'] == WARN:
return "<p style=\"color:yellow\">"+logObj['text']+"</p>\n"
if logObj['type'] == ERROR:
return "<p style=\"color:red\">"+logObj['text']+"</p>\n"
if logObj['type'] == EXCITE:
return "<p style=\"color:blue\">"+logObj['text']+"</p>\n"
return "<p style=\"color:white\">"+logObj['text']+"</p>\n"
def printerStream(self):
self.isStreaming = True
self.logs = self.getStoredLogs()
self.logs.extend(self.secondaryLogs)
self.storeLogs(self.secondaryLogs)
self.secondaryLogs = deque()
def generate():
try:
while True:
if len(self.logsToStore) > 0:
self.storeLogs(self.logsToStore)
self.logsToStore = deque()
nextLog = self.getNextLog()
nextLogHTML = self.getLogHTML(nextLog)
yield nextLogHTML
except GeneratorExit:
self.isStreaming = False
self.isStreaming = False
return Response(generate(), mimetype='text/html') # maybe text/html?
index.html.jinja:
<!doctype html>
<head>
<title>Title</title>
<style>
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
body {
color: green
}
.title {
display: flex;
flex-direction: row;
justify-content:center
}
h1 {
margin-bottom: 6px;
}
.row {
display: flex;
}
.column {
flex: 50%
}
</style>
</head>
<body>
<div class="title">
<h1>Title</h1>
<h2>Subtitle</h2>
</div>
<div class="row">
<div class="column">
</iframe src="{{ url_for('log_stream')}}">
</div>
<div class="column">
<div class="row">
<div class="column">
<p>Products: </p>
</div>
<div class="column">
{% for product in products %}
<p>{{product.name}}</p>
{% endfor %}
</div>
</div>
<div class="row">
<div class="column">
<p>Status: </p>
</div>
<div class="column">
<p>{{ status }}</p>
</div>
</div>
</div>
</div>
</body>
Actually, I solved this by adding styling to the <iframe>. Changing it to:
<iframe frameborder='0' noresize='noresize'
style='position: absolute; background: transparent; width: 100%; height:100%;'
src="{{ url_for('log_stream')}}"
frameborder="0"></iframe>
accomplished pretty much what I wanted!
So I was doing a django project by following a youtube video. And I got this error:
"Forbidden (403) CSRF verification failed. Request aborted."
everytime when I submit any data in my sign-up.html file.
Then I realize I did not configure ajax correctly. So I search online and saw the django documentation of ajax. I made some changes in my html code. still, it did not solve my problem.
I am still getting the same result. What is my mistake here. Did I made any mistake while configuring ajax?
"assets/js/django-ajax.js"
This is where i save the jquery file.
Its been a while since I am stuck in this problem.
Thank you for your time
My sign-up.html file:
{% load static %}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Instapic</title>
<link rel="stylesheet" href="{% static 'assets/bootstrap/css/bootstrap.min.css' %}">
<link rel="stylesheet" href="{% static 'assets/css/Login-Form-Clean.css' %}">
<link rel="stylesheet" href="{% static 'assets/css/styles.css' %}">
</head>
<body>
<div class="login-clean">
<form method="post">
{% csrf_token %}
<h2 class="sr-only">Login Form</h2>
<div class="illustration">
<div style="display: none" id="errors" class="well form-error-message"></div>
<img src="{% static 'assets/img/logo.jpg' %}">
</div>
<div class="form-group">
<input class="form-control" id="username" type="text" name="username" required="" placeholder="Username" maxlength="20" minlength="4">
</div>
<div class="form-group">
<input class="form-control" id="email" type="email" name="email" required="" placeholder="Email" maxlength="100" minlength="6">
</div>
<div class="form-group">
<input class="form-control" id="password" type="password" name="password" required="" placeholder="Password" maxlength="20" minlength="6">
</div>
<div class="form-group">
<button class="btn btn-primary btn-block" id="go" type="submit">Create Account</button>
</div>Already got an account? Login here ...</form>
</div>
<script src="{% static 'assets/js/jquery.min.js' %}"></script>
<script src="{% static 'assets/bootstrap/js/bootstrap.min.js' %}"></script>
<script src="{% static 'assets/js/django-ajax.js' %}"></script>
<script type="text/javascript">
$(document).ready(function() {
$('#go').click(function() {
$.post("ajax-sign-up",
{
username: $("#username").val(),
email: $("#email").val(),
password: $("#password").val()
},
function(data, status){
if (JSON.parse(data).Status == 'Success') {
window.location = '/';
} else {
$('#errors').html("<span>" + JSON.parse(data).Message + "</span>")
$('#errors').css('display', 'block')
}
});
return false;
})
})
</script>
</body>
</html>
My ajax configureation:
// using jQuery
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');
function sameOrigin(url) {
// test that a given url is a same-origin URL
// url could be relative or scheme relative or absolute
var host = document.location.host; // host + port
var protocol = document.location.protocol;
var sr_origin = '//' + host;
var origin = protocol + sr_origin;
// Allow absolute or scheme relative URLs to same origin
return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
(url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
// or any other URL that isn't scheme relative or absolute i.e relative.
!(/^(\/\/|http:|https:).*/.test(url));
}
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
Your click handler does not prevent the event from propagating. When your event handler has run the event will propagate and will eventually submit the form as a regular browser POST. You need to prevent this from happening
$('#go').click(function(event) {
event.stopPropagation();
I would suggest, add your csrf_token in every ajax.post for test, to be sure that generated token in cookies is correct.
Example:
$.ajax({
type: 'POST',
url: "",
data: {
username: $("#username").val(),
email: $("#email").val(),
password: $("#password").val(),
'csrfmiddlewaretoken': getCookie('csrftoken')
}
})
In your code. you defined method getCookie in JS, create variable csrf_token and implement this variable in ajaxSetup. Well, token is changing, but your script does not reload it.
If you want to use ajax.setup, put inside there the method getCookie, to be sure that ajax before send retakes correct token.
I want to use ajax to restart servers from a flask web app.
My solution
Iterate over a folder of .bat files that restart servers, and send the name of the file to a flask function.
In my html, I'm using jinja2 to loop over files, and then create links to the ajax call.
Problem
something is wrong with my ajax, because it doesn't do anything
here is the view.
#app.route('/restartajax/<computer>')
def restartajax(computer):
print 'code'
def runJob(computer):
try:
subprocess.call(r"\\covenas\decisionsupport\meinzer\production\bat\restart\%s" % computer)
except Exception,e:
print 'there was an exception', e
thr = Thread(target = runJob, args = [computer])
thr.start()
return jsonify(result=computer)
html
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="{{
url_for('static', filename='jquery.js') }}">\x3C/script>')</script>
<script type=text/javascript>
$SCRIPT_ROOT = {{ request.script_root|tojson|safe }};
</script>
<div class="col-md-12">
<div class="well well-lg">
<div class="container">
<h1>Restart a Computer or Server</h1>
<p>Clickit.</p>
{% for item in restartFiles %}
{% if 'Backup' not in item and 'dummy' not in item %}
<div class="col-md-4">
<script type=text/javascript>
$(function() {
$('a#calculate').bind('click', function() {
$.getJSON($SCRIPT_ROOT + '/restartajax/'+item, {
}, function(data) {
$("#result").text(data.result);
});
return false;
});
});
</script>
<h4>{{item}}</h4>
<span id=result>?</span>
<p><a href=# id=calculate>restart {{item}}</a>
</div>
{%endif%} {%endfor%}
Modifications
I modified based on the answer, and it works!
{% for item in restartFiles %}
<div class="col-md-4">
<script type=text/javascript>
$(function() {
$('a.calculate').bind('click', function() {
var item = $(this).attr('id');
$.getJSON($SCRIPT_ROOT + '/restartajax/'+item, {
}, function(data) {
$("#result").text(data.result);
});
return false;
});
});
</script>
<h4>{{item}}</h4>
<span class="result">?</span>
<p>restart {{ item }}
</div>
{%endif%} {%endfor%}
the view
#app.route('/restartajax/<computer>')
def restartajax(computer):
def runJob(computer):
try:
subprocess.call(r"\\covenas\decisionsupport\meinzer\production\bat\restart\%s" % computer)
except Exception,e:
print 'there was an exception', e
thr = Thread(target = runJob, args = [computer])
thr.start()
return jsonify(result=computer)
item doesn't seem to be defined inside your calculate function, and you haven't given it any way to work it out. You need to send something to the function that identifies which item you have clicked on.
Also, since you have multiple items, you need to choose a different ID for each link: it's invalid in HTML to have more than one ID with the same value. Use a class instead of an ID to bind the jQuery listener.
restart {{item}}
$('a.calculate').bind('click', function() {
var item = $(this).attr('id');
$.getJSON ...