Relevant information:
1) First post on here, go easy.
2) I'm a noob.
3) Trying to learn python/Django.
What I'm trying to do:
1) Create an english -> pig latin translator (written in python) and have it work in browser.
How I want it to work:
1) User clicks "translate" button, which then uses my existing python function to translate their input.
2) The translation is then displayed below the input.
What I've done so far:
1) Created .py file that successfully translates english -> pig latin in the console.
def pigLatin(sentence):
translation = " "
for word in sentence.split():
if word[0] in "aeiou":
translation += word + "yay "
if word[0] and word[1] not in "aeiou":
translation += word[2:] + word[0:2] + "ay"
print("hai")
else:
translation += word[1:] + word[0] + "ay "
return translation
sentence = input("Enter word/sentence you want translated to pig latin below: ")
print(pigLatin(sentence))
2) Used Jinja/added some HTML and bootstrap (please see below)
What it looks like in browser
3) Created a Django project, and installed my pig latin app, my folders are structured as so:
--mysite
|
|--pigLatinApp
|----templates
|------pigLatinApp
|--------home.html
|--------header.html
3) Attempted to use Ajax to get my button working, my HTML files and views.py are as follows:
header.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Pig Latin Translator</title>
{% load staticfiles %}
<link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}" type="text/css">
</head>
<body class="body">
<section id="translatorSection">
<!------------------Log Sum Container-------------------------->
<div class="container" id="translatorContainer">
{% block content %}
{% endblock %}
</div>
</section>
<script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.9.0.min.js">
</script>
</body>
</html>
home.html
{% extends "pigLatinApp/header.html" %}
{% block content %}
<div class="row">
<div class="col-md-6">
<form>
<h3>Pig Latin Translator</h3>
<p>Enter below what you want translated!</p>
<input type="string" class="form-control" placeholder="Type what you want translated here!" id="inputSumA">
<button id="translateToPig" class="btn btn-success form-control">Translate</button>
<div id="displayTranslation">
<p>{{ output }}</p>
</div>
</form>
</div>
</div>
<script>
$("#translateToPig").click(function() {
$.get("/output/", function(data) {
$("#displayTranslation").html(data);
}, "html");
});
</script>
{% endblock %}
views.py
from django.shortcuts import render
from django.http import HttpResponse
def index(request):
return render(request, 'pigLatinApp/home.html')
def output(request):
if request.is_ajax():
py_obj = pigLatinTranslator.test_code(10)
return render(request, 'pigLatinApp/output.html', {'output': py_obj.a})
What actually happens when I click the button:
1) Nothing... The page seems to refresh.
Any and all help would be appreciated, cheers!
Here:
<script>
$("#translateToPig").click(function() {
$.get("/output/", function(data) {
$("#displayTranslation").html(data);
}, "html");
});
</script>
Your click event handler doesn't prevent the event's default action, so your form is submitted by the browser. Since your form has no 'action' attribute it's submitted to the current url, so the index view is called and the page is reloaded.
You can prevent this by calling preventDefault() on the event ie:
<script>
$("#translateToPig").click(function(evt) {
evt.preventDefault(); # prevents posting the form
evt.stopPropagation(); # make sure it doesn't bubble up
$.get("/output/", function(data) {
$("#displayTranslation").html(data);
}, "html");
});
</script>
Now there are a couple things that could be improved in your code but that's another topic. At least I think you should first try to get something working without ajax, so you learn the whole request/response cycle stuff, working with GET and POST, using django forms etc.
I recommend trying a normal request i.e. not ajax and also creating a form.py where you can create a form class for the search. In your views import the pig latin translator function and call it in your output function.
Related
I'm trying to execute a function based on a button click via javascript.
I've copied a tutorial on how to do this, but nothing happens.
I've added a break point in the function that should be executed (background_process_test), but the program never executes the function.
What am I missing to get this simple tutorial working?
I'm running on a local machine with waitress.
python code:
from flask import Flask, render_template, request
from flask import jsonify
from waitress import serve
app = Flask(__name__)
#rendering the HTML page which has the button
#app.route('/json')
def json():
return render_template('json.html')
#background process happening without any refreshing
#app.route('/background_process_test')
def background_process_test():
print ("Hello")
return ("nothing")
if __name__ == "__main__":
app.debug = True
serve(app, host='0.0.0.0', port=8080) #WAITRESS!
html code:
<!DOCTYPE html>
<html lang="en">
<head>
<!--<script src="/jquery/jquery-3.6.0.min.js"></script>-->
<script src="{{url_for('static', filename='jquery-3.6.0.min.js')}}"></script>
<script type=text/javascript>
(function() {
('a#test').on('click', function(e) {
e.preventDefault()
$.getJSON('/background_process_test', function(data) {
//do nothing
})
return false;
})
})
</script>
</head>
<body>
<div class='container'>
<h3>Test</h3>
<form>
<a href=# id=test><button class='btn btn-default'>Test</button></a>
</form>
</div>
</body>
</html>
Update:
Network tab
i somehow deleted the '$' sign. It was giving an error due to spacing in visual studio. Setting the spacing right, solved the issue. Many thanks for pointing me in the right direction.
There is a typo in the following code:
('a#test').on('click', function(e) {
...
})
Specifically, your attempt to use jquery get the list of elements that match 'a#test'. The code should be:
$('a#test').on('click', function(e) {
...
})
I know nothing about it.
I need to make a simple website.
I will take an input from user.
Suppose the input is 'LOL'
Then I need to open a new tab with this url - "https://www.help.me/LOL"
#Help me Please
You can do it by using django forms
In your project directory in views.py file you can use this code
from django import forms
from django.http import HttpResponseRedirect
class inputform(forms.Form):
inputfield = forms.CharField(label="Input")
def index(request):
if request.method == "POST":
x = inputform(request.POST)
if x.is_valid():
y = x.cleaned_data["inputfield"]
return
HttpResponseRedirect(f"https://www.help.me/{y}")
return render(request, "index.html", { "form":
inputform() }
In HTML, you can write the following code to represent the Input Field in HTML page
in index.html;
<!DOCTYPE html>
<html lang="en">
<head>
<title> xyz </title>
</head>
<body>
<form method="POST">
{% csrf_token %}
{{form}}
<input type="submit">
</form>
</body>
</html>
By this you will get your desired results
I've been teaching myself python and Django and wanted to show a clickable map on a webpage. I don't know javascript but I found jvectormap and it seems to be easy and works well.
However I am confused about template tags. With the code below I can show a world map, and using the onregion function can get the country code and send it to an alert, if I comment out the alert, I can send using the Django URL tag to another web page.
{% load static %}
{% load static %}
{{params}}
<!DOCTYPE html>
<html>
<head>
<title>jVectorMap demo</title>
<link href="{% static 'css/jquery-jvectormap-2.0.5.css' %}" rel="stylesheet" type="text/css" media="screen"/>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="{% static 'js/jquery-jvectormap-2.0.5.min.js' %}"></script>
<script src="{% static 'js/jquery-jvectormap-world-mill-en.js' %}"></script>
</head>
<body>
<div id="world-map" style="width: 600px; height: 400px"></div>
<script>
$(function(){
$('#world-map').vectorMap({ map: 'world_mill_en',
onRegionClick:function(event, code){
var message = (code);
alert( code );
window.location.assign ("{% url 'mainapp:home2' %}")
}
});
});
</script>
</body>
</html>
So a couple of questions:
I thought I should be able to use the template tag in the alert like alert( {{params}} ) but that doesn't seem to work. I thought you might be able to pass the string in params that way. I saw found a different post that suggested wrapping the variable with a tag
'''
{{ params }}
'''
is that a good approach to use tags to get variables into the javascript?
More importantly with the URL template tag, I would like to pass the country code or other information back to the view. In the documentation it looks like you can either use:
{% url 'some-url-name' v1 v2 %}
or
{% url 'some-url-name' arg1=v1 arg2=v2 %}
How would I modify my current view and URL with that approach?
def home(request):
params='this is the home page '
return render(request,'mainapp/home.html',{'params':params})
Do I just start by replacing the return with a redirect?
return redirect('some-view-name', params= code )
and then set up a url path where the code is passed as an id or a slug or something?
Is there different way I should be trying where the onregion or an java onclick script sends something back to django?
Sorry for the multiple questions, but in learning mode...
To answer my own question, I found the following on stack overflow that were helpful in understanding.
Django Template Variables and Javascript
Get javascript variable's value in Django url template tag
and several others.
The short answer is that the template tags once rendered are just text in the html file.
1) You can assign a javascript variable something from a template tag, but that is probably not a great idea in some cases since it could be misused.
2) Since the template tag is just text in the file, there are ways to put a placeholder and then use the .replace function to alter the placeholder and then reverse the URL. The usual way seems to have the placeholder be a number that would never be accessed and and replace the placeholder with a pk or an object id.
3) Some people point out that using GET statement is better and simpler. Somehow AJAX can be used to do this. I'm just learning how to spell Ajax so I will leave it to others to explain.
I have a form in my Flask app. I need the form submission to be mediated by Javascript (JS). The desired behavior is that on submission of the form, we get an immediate redirect, then JS talks to Flask, Flask sends a response, JS updates the DOM.
Problem: The form doesn't submit to JS. On submission, the text in the input box clears, and the page sits there. No errors log to the console
It appears to ignore my JS, though the <script> tags are in order, their placement in layout.html is correct, and http://localhost:5000/static/index.js displays the file. I inserted a console.log statement to test if the appropriate JS function was being fired. Got nothing. I enclosed everything in $(document).ready(). Still nothing. Placing a method="post" attribute in the <form> tag and a name attribute in the form's input box allowed me to submit directly to Flask, but I need it to go to JS. All of this is playing out on my machine, so no CORS. Where am I going wrong?
Form that must go to JS then Flask
<div class="container">
<div class="display-3">
<strong>Create A Channel</strong>
</div>
<form id="channelForm" class="mt-4">
<label for="channelName">Channel Name</label>
<input id="channelName" class="form-control" type="text" placeholder="Enter Channel Name">
<input type="submit" class="btn btn-primary" value="Create Channel">
</form>
</div>
Abbreviated JS
document.querySelector('#channelForm').onsubmit = () => {
console.log("here");
window.location.href = 'messages.html';
// other stuff that links to Flask route
};
Flask route
#app.route('/channels', methods=["GET", "POST"])
def channels():
channelList = []
if request.method == "POST":
channel = request.form.get("channel")
if not (channel is None) and not (channel in channelList):
channelList.append(channel)
print(channelList)
return jsonify({"success": True, "channel":channelList})
else:
return jsonify({"success": False})
else:
return render_template("channels.html")
Head section from layout.html
<head>
{% block head %}
<!-- Bootstrap 4 -->
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB" crossorigin="anonymous">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.2.0/css/all.css" integrity="sha384-hWVjflwFxL6sNzntih27bfxkr27PmbbK/iSvJ+a4+0owXq79v+lsFkW54bOGbiDQ" crossorigin="anonymous">
<!-- Additional CSS -->
<link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">
<!-- JS -->
<script src="{{ url_for('static', filename='index.js') }}"></script>
{% endblock %}
</head>
EDIT
When I hit the button to submit the form, I see "GET /static/index.js HTTP/1.1" 200 - in the terminal. Still nothing in the console, but I thought a GET request was unusual, given I was hitting a button to submit a form. Was expecting POST.
The problem is your form is being submitted through HTTP protocol (traditional form submission) rather than JS. To prevent this, you need to stop your button click from submitting the form:
var form = document.querySelector('#channelForm'),
button = form.querySelector('input.btn-primary');
button.addEventListener('click', function(e) {
e.preventDefault();
console.log('process form data!');
})
Also, place your JavaScript include after your HTML inclusions, so the elements targeted by your JS are on the page when the JS loads.
What might be happening is that the response from your server is quicker than you realize. You're not preventing the default onsubmit functionality, so you might not actually see the JS run in your console. To see this, you can try to turn on a preserve logs between navigations setting. But what you likely need is to prevent the default and then directly send your request to your server:
document.querySelector('#channelForm').onsubmit = (event) => {
event.preventDefault()
...
// AJAX request to your server with your data
};
I am trying to download the top stories of the BBC website. and display them on a HTML web page. previously I tried to do this through ajax in javascript.However, I get the error that:
"XMLHTTPRequest cannot load my page as no 'Access-Control-Allow-Origin' header is present on the requested resource.cso is therefore not allowed access."
I did some more research and found that as I am doing this in Django, I need to request the object from the URL using my views.py file, not ajax.
Ive been reserching most of today, with no sucess, so was wondering if someone could help me or forward me to some links which can!
My current code is as follows:
News.js:
$(document).ready(function(){
function an(){
$("#TopNews").append("<ul></ul>");
$.ajax({
type: "GET",
url: "http://rss.cnn.com/rss/cnn_topstories.rss",
dataType: "xml",
success: function upon_success ( xml ) {
if(response.status === "success"){
$(xml).find('item').each(function(){
var Titles = $(this).find('title').text();
$("<li></li>").html(Titles).appendTo("#TopNews ul");
});
}
else if (response.status === "error"){
alert("The XML File could not be processed correctly.");
}
}
});
};
$("#btn").click(an);
});
Html:
{% load staticfiles %}
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script type="text/javascript" src={% static "js/News.js" %}></script>
</head>
<body>
<h1>Top News: BBC versus CNN</h1>
<input type="submit" id="btn" value="Refresh"></imput>
<ul id="TopNews"></ul>
</body>
</html>
Views.py: views
You can make the request in views.py (your pic of views.py looks like urls.py) by using something like the Python requests library:
import requests
def your_view(request):
xml_news = requests.get('<your url>')
news = #maybe some parsed version of your xml
return render(request, 'your_page.html', {'news': news})
Then, you can change your template to include something like:
{% for item in news %}
<li>{{ item }}</li>
{% endfor %}
Otherwise, use your javascript to add the xml to your page like you have in your example.