Integrating Flask-Python with HTML and JavaScript - javascript

In my code , I want the Javascript defined in index.html page to run when a particular condition in app.py is true, else the script should not run. How can I achieve this?
app = Flask(__name__)
#app.route('/',methods=["GET","POST"])
def index():
#print "came here"
if request.method == 'POST':
search_token = request.args.get("validationtoken")
print "search", search_token
if search_token != None:
# text = search_token
resp = Response(search_token, status=200, mimetype='plain/text')
print "resp",resp
return resp
else:
print " Notification received "
##### HERE I NEED TO CALL THE Java SCRIPT DEFINED IN HTML PAGE TO EXECUTE
elif request.method=="GET":
code=request.args.get('code')
state=request.args.get('state')
----
pls help..

The python script should go like this
app = Flask(__name__)
#app.route('/',methods=["GET","POST"])
def index():
script = False
if request.method == 'POST':
search_token = request.args.get("validationtoken")
print "search", search_token
if search_token != None:
# text = search_token
resp = Response(search_token, status=200, mimetype='plain/text')
print "resp",resp
return resp
else:
print " Notification
script = True
render_template('index.html', Script=script)
elif request.method=="GET":
code=request.args.get('code')
state=request.args.get('state')
----
And the index.html should be something like this
{% if Script %}
<script type="text/javascript">
"Your code lies here"
</script>
You can pass the variable in your python script (Your app) to the index.html template using this way as Flask uses Jinja templates.

Related

Flask-socketio, send message only to one chat

I am developing flask app with chat feature. When somenone sends message, it saves into db. Now I want to display it on screen with socketio but when someone sends message, it shows in every currently used chat. Does anyone know how to display message only in one correct chat? Every two users have own chat with ID or can create it by sending message.
main.py code:
#app.route('/chat/<int:id>', methods=['GET', 'POST'])
#login_required
def chat(id):
chat = Chats.query.get_or_404(id)
form = MessageForm()
messages = chat.messages
chat_id = chat.id
if current_user.id == chat.first_user or current_user.id == chat.second_user:
if request.method == "POST":
form1 = request.form.get("myMessage")
chat_id = chat.id
author = current_user.id
message = Messages(author=author, chat=chat_id, content=form1)
chat.last_message = datetime.utcnow()
db.session.add(message)
db.session.commit()
return render_template('chat.html', chat=chat, messages=messages, form=form, chat_id = chat_id)
else:
return redirect(url_for('index'))
#socketio.on('message')
def handleMessage(msg):
print('Message: ' + msg)
send(msg, broadcast=True)
chat.html code:
<script type="text/javascript">
$(document).ready(function() {
var socket = io.connect('http://127.0.0.1:5000');
socket.on('connect', function() {
socket.send('User has connected!');
});
socket.on('message', function(msg) {
$("#messages").append('<li>'+msg+'</li>');
console.log('Received message');
});
$('#sendbutton').on('click', function() {
socket.send($('#myMessage').val());
$('#myMessage').val('');
});
});
</script>
<ul id="messages"></ul>
<input type="text" id="myMessage">
<button id="sendbutton">Send</button>

Serve file with Flask's send_file then redirect to another page

I want to download a file and at the same time redirect to a new page. The user is shown a page with a link for the download. When they click it, I want to start the download then redirect to another page so they can't keep clicking it. However, I can only seem to get one or the other to work.
from flask import Flask, render_template, redirect, url_for, session, request, flash, send_file
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField, BooleanField
from pytube import YouTube
import os
import random, string
import re
app = Flask(__name__)
app.config['SECRET_KEY'] = 'mysecretkey'
session_id = ''.join(random.choices(string.ascii_letters + string.digits, k=6))
class url_form(FlaskForm):
link = StringField('Enter link of YouTube video you would like to convert...')
audio = BooleanField('Audio Only')
submit = SubmitField('Convert')
def download_video(link, just_audio):
yt = YouTube(link)
download_path = 'conversions/'
#global myvar
if just_audio == True:
stream = yt.streams.filter(only_audio=True).first()
tag = 'video'
else:
stream = yt.streams.filter(adaptive=True).first()
tag = 'audio only'
download_video.name = yt.title
download_video.cleanString = re.sub('[^a-zA-Z0-9 \n\.]', '', download_video.name)
download_video.thumbnail = yt.thumbnail_url
download_video.path = stream.download(filename = download_video.cleanString, output_path = download_path)
return
#app.route('/', methods=['GET', 'POST'])
def index():
result = False
form = url_form()
if form.validate_on_submit():
session['link'] = form.link.data
if form.audio.data:
just_audio = True
else:
just_audio = False
session['just_audio'] = just_audio
link = session.get('link')
just_audio = session.get('just_audio')
download_video(link, just_audio)
#download_video(link, just_audio)
#return send_file(download_video.path, attachment_filename=download_video.cleanString + '.mp4', as_attachment=True)
return redirect(url_for('conversion_complete'))
return render_template('index.html', form=form, result=result)
#app.route('/conversion_complete', methods=['GET', 'POST'])
def conversion_complete():
return render_template('conversion_complete.html')
#app.route('/download/', methods=['GET'])
def download():
return send_file(download_video.path, attachment_filename=download_video.cleanString + '.mp4', as_attachment=True)
return render_template('result.html')
<html>
<body>
<h1>Conversion Complete</h1>
<a href='download' target='blank' type='button'><button class='btn btn-default'>Download!</button></a>
</body>
</html>

How to update image input with django forms and template

I have a django project where a user has a profile and can upload a profile picture. The models.py is:
`class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
name = models.CharField(max_length=64,blank=True)
profilePic = models.ImageField(blank=True, null=True, upload_to= "profile/")
phoneNumber = models.CharField(max_length=12,blank=True)
streetAddress = models.CharField(max_length=64,blank=True)`
On my site, the user can edit his profile including the profile picture. To do so, I have a form, where the initial values are the ones initially stored. The forms.py is:
class EditProfile(forms.ModelForm):
def __init__(self, profile, *args, **kwargs):
self.profile = profile
super(EditProfile, self).__init__(*args, **kwargs)
self.fields['name'] = forms.CharField(label='Name:', initial= profile.name,required=False)
self.fields['phoneNumber'] = forms.CharField(label= "Phone Number:", initial= profile.phoneNumber,required=False)
self.fields['streetAddress'] = forms.CharField(label='Street Address and/or Postal Code:', initial= profile.streetAddress,required=False)
self.fields['profilePic'] = forms.ImageField(label='Profile Picture:', initial= profile.profilePic,required=False)
class Meta:
model = Profile
fields = ("name", "phoneNumber","streetAddress", "profilePic")
This part works great, and on my site I can see the stored values. The problem is when I try to edit them and submit the form.
My views.py is:
def settings(request):
user= request.user
if request.method == 'GET':
userProfile = Profile.objects.get(user=user)
f1= UserProfile(user=request.user)
f2= EditProfile(profile=userProfile)
return render(request, 'listings/settings.html', {'form': f1,'form2': f2})
elif request.method == 'POST':
userProfile = Profile.objects.get(user=user)
f1= UserProfile(user=request.user)
f2= EditProfile(profile=userProfile)
name= request.POST["name"]
phoneNumber = request.POST["phoneNumber"]
streetAddress = request.POST["streetAddress"]
Profile.objects.filter(user=user).update(name= name, phoneNumber = phoneNumber, streetAddress = streetAddress)
if "profilePic" in request.FILES:
image1=request.FILES["profilePic"]
fs1=FileSystemStorage()
fs1.save(image1.name, image1)
userProfile.profilePic = image1
userProfile.save()
else:
userProfile.profilePic.delete()
messages.success(request, 'Your profile has been updated!')
return redirect("/settings")
Everything gets edited with no issues except for the imageFile. If I upload the file, it works and the image is updated. However, if I make no changes to the imageFile (i.e. I want to keep the same image), the request.FILES is empty, and then the code goes to the else statement and deletes the existing profilePic.
My question is that the I can see the initial profile picture on my site, so the forms.py is working, but why isn't it being submitted along with the rest of the form?
Your question is a bit confusing, but it seems that you are trying to reinvent the wheel. If you want to have the "initial" data reinserted into the form, you should use the native instance parameter. You can use it as such:
profile = Profile.objects.get(user=user)
# This can be in your GET
profile_form = EditProfile(instance=profile)
# This can be in your POST
profile_form = EditProfile(request.POST, request.FILES, instance=profile)
profile_form.save()

CSRF validation failed when integrate CKeditor to Flask

I am integrating CKeditor to Flask to add rich text support. But when file upload feature is enabled, the post request is always failed. It should be the csrf problem. Added {{csrf_token()} directly doesn't work. Is there anyplace in CKeditor should be changed to add csrf?
{% block content %}
<h1>Add articile:</h1>
<form>
<input type="hidden" name="csrf_token" value="{{csrf_token()}}" />
<textarea name="editor1" id="editor1" rows="20" cols="80">
This is my textarea to be replaced with CKEditor.
</textarea>
<script type="text/javascript">
CKEDITOR.replace('editor1', {
filebrowserUploadUrl: '/ckupload',
});
</script>
</form>
{% endblock %}
To handle file upload,
def gen_rnd_filename():
filename_prefix = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
return '%s%s' % (filename_prefix, str(random.randrange(1000, 10000)))
#app.route('/ckupload', methods=['POST', 'OPTIONS'])
def ckupload():
"""CKEditor file upload"""
error = ''
url = ''
callback = request.args.get("CKEditorFuncNum")
print callback
print request.method
if request.method == 'POST' and 'upload' in request.files:
fileobj = request.files['upload']
fname, fext = os.path.splitext(fileobj.filename)
rnd_name = '%s%s' % (gen_rnd_filename(), fext)
filepath = os.path.join(app.static_folder, 'upload', rnd_name)
dirname = os.path.dirname(filepath)
if not os.path.exists(dirname):
try:
os.makedirs(dirname)
except:
error = 'ERROR_CREATE_DIR'
elif not os.access(dirname, os.W_OK):
error = 'ERROR_DIR_NOT_WRITEABLE'
if not error:
fileobj.save(filepath)
url = url_for('static', filename='%s/%s' % ('upload', rnd_name))
else:
error = 'post error'
res = """<script type="text/javascript">
window.parent.CKEDITOR.tools.callFunction(%s, '%s', '%s');
</script>""" % (callback, url, error)
response = make_response(res)
response.headers["Content-Type"] = "text/html"
return response
Current my workaround is to add csrf exception to this url.
#csrf.exempt
CKEditor use AJAX to send uploads, so you can add CSRF support in this way:
<script type="text/javascript">
CKEDITOR.replace( "textarea-name", {
fileTools_requestHeaders: {
'X-CSRFToken': '{{ csrf_token() }}',
},
});
</script>
BTW, I recommend use Flask-CKEditor to integrate CKEditor with Flask-WTF, it makes this usage easier:
from flask_wtf import CSRFProtect
app = Flask(__name__)
# the secret key used to generate CSRF token
app.config['SECRET_KEY'] = 'dev key'
# enable CSRF protection
app.config['CKEDITOR_ENABLE_CSRF'] = True
csrf = CSRFProtect(app)

Inject Javascript into web page with Python

For my application I need to inject JS into the loaded url.
I am using the following snippet from here https://stackoverflow.com/a/10866495/1162305
import wx
import wx.html2
class MyBrowser(wx.Dialog):
def __init__(self, *args, **kwds):
wx.Dialog.__init__(self, *args, **kwds)
sizer = wx.BoxSizer(wx.VERTICAL)
self.browser = wx.html2.WebView.New(self)
sizer.Add(self.browser, 1, wx.EXPAND, 10)
self.SetSizer(sizer)
self.SetSize((700, 700))
if __name__ == '__main__':
app = wx.App()
dialog = MyBrowser(None, -1)
dialog.browser.LoadURL("http://www.google.com")
dialog.Show()
dialog.browser.RunScript('alert("hello");')
app.MainLoop()
Here I am injecting javascript with RunScript but the problem is, this javascript loads before the webpage loads. How can I load this javascript after the webpage (given url) loaded completely.
I know in plain javascript I can use document.readyState === "complete", but here how can I do it?
According to documentation:
http://wxpython.org/Phoenix/docs/html/html2.WebView.html#phoenix-title-asynchronous-notifications
You should use EVT_WEBVIEW_LOADED event to check if asynchronous methods like LoadURL is completed.
self.Bind(wx.html2.EVT_WEBVIEW_LOADED, self.OnWebViewLoaded, self.browser)
Complete code could look something like (not tested):
import wx
import wx.html2
class MyBrowser(wx.Dialog):
def __init__(self, *args, **kwds):
wx.Dialog.__init__(self, *args, **kwds)
sizer = wx.BoxSizer(wx.VERTICAL)
self.browser = wx.html2.WebView.New(self)
sizer.Add(self.browser, 1, wx.EXPAND, 10)
self.Bind(wx.html2.EVT_WEBVIEW_LOADED, self.OnWebViewLoaded, self.browser)
self.SetSizer(sizer)
self.SetSize((700, 700))
def OnWebViewLoaded(self, evt):
# The full document has loaded
self.browser.RunScript('alert("hello");')
if __name__ == '__main__':
app = wx.App()
dialog = MyBrowser(None, -1)
dialog.browser.LoadURL("http://www.google.com")
dialog.Show()
app.MainLoop()

Categories

Resources