PhantomJS not loading CSS styles - python

Hi I'm using PhantomJS v 2.1.1 via WebDriver in my Django app tests. But from screenshot in one problematic test it isn't loading CSS.
I need to test that there are some buttons in Bootrap modal but it's not displayed at all.
Browser init in test setup:
self.browser = webdriver.PhantomJS(executable_path=settings.PHANTOMJS_PATH)
self.browser.set_window_size(1920, 1080)
And test code it self:
self.browser.get(self.live_server_url + "/accounts/login/")
self.browser.find_element_by_name("login").clear()
self.browser.find_element_by_name("login").send_keys(user.email)
self.browser.find_element_by_name("password").clear()
self.browser.find_element_by_name("password").send_keys(password)
self.browser.find_element_by_id("submit").click()
self.browser.find_element_by_id("logout").click()
self.browser.implicitly_wait(10)
self.assertEqual("Ano", self.browser.find_element_by_xpath("/html/body/div[4]/div/div/div[3]/button[2]").text)
self.assertEqual("Ne", self.browser.find_element_by_css_selector("div.modal-footer").text)
Lastly here is part of HTML page that produce expected modal:
<li>
<a href="#" id="logout" style="color: #ffffff">
<span class="glyphicon glyphicon-log-out"></span>
</a>
</li>
$(document).ready(function () {
$("#logout").on("click", function (e) {
e.preventDefault();
bootbox.dialog({
message: '<div class="row"> ' +
'<div class="col-md-12"> ' +
'<form class="form-horizontal" id="confirm-logout" method="post" action="/accounts/logout/"> ' +
"<input type='hidden' name='csrfmiddlewaretoken' value='lmXDBtPw6wSDMClUEIKOxzd8fvc3KCFL' />" +
'<div class="form-group"> ' +
'<div class="col-md-8"> ' +
'<div class="checkbox">' +
'<label>' +
'<input type="checkbox" ' +
'value="no-dialog" name="logout-confirm"> Zobrazovat tento dialog' +
'</label>' +
'</div>' +
'</div> ' +
'</div> </div>' +
'</form> </div> </div>',
title: "Odhlásit",
buttons: {
danger: {
label: "Ne",
className: "btn-danger",
callback: function () {
bootbox.hideAll()
}
},
main: {
label: "Ano",
className: "btn-primary",
callback: function () {
$("#confirm-logout").submit();
}
}
}
});
});
....
}
All CSS and JS files are loaded from django dev-server. They are located in static dir. Here's part of HTML head:
<link rel="icon" href="/static/img/favicon.ico">
<link rel="stylesheet" href="/static/css/base_style.css">
<link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="/static/bootstrap/css/bootstrap-theme.min.css">
<link rel="stylesheet" href="/static/pizza-master/css/pizza.css">
<link rel="stylesheet" href="/static/css/profile_style.css">
<script src="/static/scripts/jquery_1_11.min.js"></script>
<script src="/static/scripts/bootbox.min.js"></script>
<script src="/static/scripts/jquery.confirm.js"></script>
<script src="/static/bootstrap/js/bootstrap.min.js"></script>
<script src="/static/bootstrap/js/npm.js"></script>
<script src="/static/pizza-master/js/vendor/modernizr.js"></script>
Lastly there are screenshots:
PhantomJs background is transparent
Destktop Chrome run server instead test

OK, so I'm found solution. Problem wasn't related to PhantomJS at all. ChromeDriver acting exactly same.
Problem was caused by Django tests with not serving static files same way as runserver did.
Solution with worked for me is run:
python manage.py collectstatic
This ensure that test server serve static files if your django have setup static files. Django static files doc

Related

CSS is not linked to HTML(template) file successfully and nothing happens when I change the CSS - Django

I just finished reading Django document and I'm trying to deploy a website with it.
I linked all the style sheets to HTML file(template) but when I change the CSS file(like changing color), nothing change. Furthermore the pre loader don't work and Its just spinning.
Directory Structure:
HTML file header:
<link rel="stylesheet" href="{% static 'css/basic.css' %}" />
<link rel="stylesheet" href="{% static 'css/layout.css' %}" />
<link rel="stylesheet" href="{% static 'css/blogs.css' %}" />
<link rel="stylesheet" href="{% static 'css/line-awesome.css' %}" />
<link rel="stylesheet" href="{% static 'css/magnific-popup.css' %}" />
<link rel="stylesheet" href="{% static 'css/animate.css' %}" />
<link rel="stylesheet" href="{% static 'css/simplebar.css' %}" />
views.py:
def home(request):
return render(request, "index.html")
setting.py:
STATIC_URL = 'static/'
STATICFILES_DIR = [
path.join(BASE_DIR, 'static'),
]
STATIC_ROOT = path.join(BASE_DIR, 'static')
And for the preloader:
HTML file:
<div class="preloader">
<div class="centrize full-width">
<div class="vertical-center">
<div class="spinner">
<div class="double-bounce1"></div>
<div class="double-bounce2"></div>
</div>
</div>
</div>
</div>
js:
$(window).on("load", function() {
var preload = $('.preloader');
var lines = $('.lines-grid');
preload.find('.spinner').fadeOut(function(){
preload.fadeOut();
lines.addClass('loaded');
});
});
I tried to delete the pre loader but when I delete the JS or the html element the page goes black at all
If your static files are loaded and when you make a change, you need to reset your browser cache. For this, you need to press the Ctrl + F5.
Sometimes you may need to run the project again, especially when you edit your settings.py file

Trigger onchange via Selenium from Python

I have a Django webapp displaying a form. One of the fields is a FileField, defined via the Django model of the form:
From models.py:
class Document(models.Model):
...
description = models.CharField(max_length=100, default="")
document = models.FileField(upload_to="documents/", max_length=500)
The document file_field has an onchange ajax function attached that will parse the uploaded filename, check some database stuff depending on it, and populate other fields on the html-page with the results.
From forms.py:
class DocumentForm(forms.ModelForm):
class Meta:
model = Document
fields = ("document",)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["customer"] = forms.CharField(initial="", required=True)
self.fields["output_profile"] = forms.CharField(initial="", required=True)
self.fields["document"].widget.attrs[
"onchange"
] = "checkFileFunction(this.value, '/ajax/check_file/')"
From urls.py:
urlpatterns = [
#...
path("ajax/check_file/", views.check_file, name="ajax_check_file")
]
From views.py:
def check_file(request):
full_data = {"my_errors": []}
my_path = pathlib.Path(request.GET.get("file_path").replace("\\", os.sep))
# parse customer ID from file_path
# get data of customer from db
# assemble everything into full_data
return JsonResponse(full_data)
This is the full html page as displayed (copied from Chrome => show source and cleaned up the indentation & whitespaces some):
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<link href="/static/css/main.css" rel="stylesheet" type="text/css">
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/themes/base/jquery-ui.css"/>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.20/css/dataTables.jqueryui.css"/>
<script src="/static/js/jquery.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
<script type="text/javascript" src="https://cdn.datatables.net/1.10.20/js/jquery.dataTables.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/1.10.20/js/dataTables.jqueryui.js"></script>
<title>
Convert RES FILE
</title>
</head>
<body>
<header id="header">
<section class="top_menu_left">
Login
<a>&nbsp|&nbsp</a>
Logout
<a>&nbsp|&nbsp</a>
Edit User
<a>&nbsp|&nbsp</a>
Register
</section>
<section class="top_menu_right">
About Us
<a>&nbsp|&nbsp</a>
Contact Us
<a>&nbsp|&nbsp</a>
Submit an issue
<a>&nbsp|&nbsp</a>
Documentation
<a>&nbsp|&nbsp</a>
Home
</section>
<div id="topbanner" >
<img src="/static/banner_small.png" alt="" width="100%" height="150"/>
</div>
</header>
<aside id="leftsidebar">
<section class="nav_account">
<h4>Submit a New Request</h3>
<ul>
<li>Get Typing Results</li>
<li>Compare Typing Results</li>
<li>Convert Typing Format</li>
</ul>
</section>
<section class="nav_tools">
<h4>View Your Requests</h3>
<ul>
<li>View My Submissions</li>
</ul>
</section>
</aside>
<section id="main">
<p> </p>
<h2>Convert Typing Results to Format of Choice</h2>
<p> </p>
<h3>Upload a file to our database</h3>
<form method="post" enctype="multipart/form-data">
<input type="hidden" name="csrfmiddlewaretoken" value="qqIKcsAynuE35MQ37dvjF5XeIyfcEbHb3wjtgygGZaigQReNxHLQewoDKcEb8Roj">
<div id="div_id_document" class="form-group">
<label for="id_document" class=" requiredField">
Document<span class="asteriskField">*</span>
</label>
<div class="">
<input type="file" name="document" onchange="checkFileFunction(this.value, '/ajax/check_file/')" class="clearablefileinput form-control-file" required id="id_document">
</div>
</div>
<input type="hidden" id="id_description" name="description" value="">
<p> </p>
<div id="div_id_customer" class="form-group">
<label for="id_customer" class=" requiredField">
Customer<span class="asteriskField">*</span>
</label>
<div class="">
<input type="text" name="customer" readonly class="textinput textInput form-control" required id="id_customer">
</div>
</div>
<div id="div_id_output_profile" class="form-group">
<label for="id_output_profile" class=" requiredField">
Output profile<span class="asteriskField">*</span>
</label>
<div class="">
<input type="text" name="output_profile" readonly class="textinput textInput form-control" required id="id_output_profile">
</div>
</div>
<div class="form-group">
<div id="div_id_notify_me" class="form-check">
<input type="checkbox" name="notify_me" style="width:15px;height:15px;" class="checkboxinput form-check-input" id="id_notify_me">
<label for="id_notify_me" class="form-check-label">
Notify me
</label>
</div>
</div>
<p>
<button class="linkbutton" type="submit" id="submit_btn">Convert</button>
<button id="create-book" class="linkbutton" type="button" name="button" style="float: right;">Create an Output Profile</button>
</p>
</form>
<div class="modal fade" tabindex="-1" role="dialog" id="modal">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content" id="form-modal-content">
</div>
</div>
</div>
<div class="modal fade" tabindex="-1" role="dialog" id="modal-check-res-file">
<div class="modal-dialog" role="document">
<div class="modal-content" id="form-modal-content-check-res-file">
</div>
</div>
</div>
<script>
var formAjaxSubmit = function(form, modal) {
$(form).on('submit', function (e) {
e.preventDefault();
console.log("submitting...");
var my_val = $("#id_profile_name").val();
var this_val = $("#confirm_save").val();
var res = this_val.split(",");
var this_val_contains_my_val = (res.indexOf(my_val) > -1);
if (this_val_contains_my_val === true) {
var conf = confirm("Are you sure want to overwrite an exsisting profile?");
}else {var conf = true;};
if (conf === true) {
$.ajax({
type: $(this).attr('method'),
url: "/new_customer_profile/",
data: $(this).serialize(),
success: function (xhr, ajaxOptions, thrownError) {
if ( $(xhr).find('.invalid-feedback').length > 0 ) {
$(modal).find('.modal-content').html(xhr);
formAjaxSubmit(form, modal);
} else {
$(modal).find('.modal-content').html(xhr);
}
},
error: function (xhr, ajaxOptions, thrownError) {
}
});
};
});
};
$('#create-book').click(function() {
console.log("hhallo");
$('#form-modal-content').load('/new_customer_profile/', function () {
var iam_alive = document.getElementById("modal");
// check if iam_alive is defined, this is required if a session expired -> in that case the modal is lost and it would redirect to an almost empty page.
if (iam_alive) {
$('#modal').modal('toggle');
formAjaxSubmit('#form-modal-body form', '#modal');
}
// if not iam_alive: redirect to login page
else {
window.location.replace('/accounts/login/');
}
});
});
$('#check-res-file').click(function() {
console.log("hhallo hier unten jetzt");
$('#form-modal-content-check-res-file').load('/check_res_file/', function () {
$('#modal-check-res-file').modal('toggle');
//formAjaxSubmit('#form-modal-body form', '#modal');
});
});
</script>
<script type="text/javascript">
$(document).ready(function() {
var mycell = document.getElementById("create-book");
mycell.style.display = "none";
});
</script>
<script>
function checkFileFunction(myfile, url) {
$.ajax({ // initialize an AJAX request
url: url, // set the url of the request (= localhost:8000/hr/ajax/load-cities/)
data: {"file_path": myfile},
dataType: 'json',
success: function (x) {
if (x.my_errors.length == 0) {
$('#id_customer').val(x.customer_name);
$('#id_output_profile').val(x.customer_profile);
$('#id_description').val(x.customer_file);
}else{
$('#id_customer').val("");
$('#id_customer').val("");
$('#id_output_profile').val("");
alert(x.my_errors);
var showme = function myFunction() {
var mycell = document.getElementById("create-book");
mycell.style.display = "block";
};
showme();
}
},
});
}
</script>
</section>
</body>
</html>
Now, I'm trying to test this with pytest via Selenium.
I can send the file path to the field via send_keys(). However, the onchange event seems not to be triggered. (It does work fine when I select the file manually.)
file_field = self.driver.find_element(By.NAME, "document")
file_field.clear()
file_field.send_keys(str(path/to/myfile))
This will register the file fine and it will be uploaded, but the onchange function never happens.
I have searched and it seems others also have encountered the problem of send_keys not triggering the onchange event. But I have not been able to implement any of the suggested solutions in my Python code. (I have not written the Django code for this app, I'm just the tester and my grasp on Django and javascript is not very good, yet. My native programming language is Python.)
The only solution I understood how to implement was sending a TAB or ENTER afterwards (file_field.send_keys(Keys.TAB)) to change the focus, but that triggers an
selenium.common.exceptions.InvalidArgumentException: Message: invalid argument: File not found
(The file I enterted does exist, the path is fine. I can successfully call .exists() on it.)
Simply selecting a different element after send_keys to shift the focus (i.e., customer_field.click()) does not trigger the onchange function of file_field, either.
How can I trigger an onchange event via Selenium from Python? Or otherwise make sure it is triggered?
First of all, your onchange specification is a bit kludgy and would be preferably specified as:
<input type="file" name="document" onchange="checkFileFunction(this.value, '/ajax/check_file/');">
I am using Selenium with the latest version of Chrome and its ChromeDriver under Windows 10 and have no problems with the onchange event being taken. This can be demonstrated with the following HTML document. If the onchange event is taken, then it should create a new div element with id 'result' that will contain the path of the filename selected:
File test.html
<!doctype html>
<html>
<head>
<title>Test</title>
<meta name=viewport content="width=device-width,initial-scale=1">
<meta charset="utf-8">
<script>
function checkFileFunction(value)
{
const div = document.createElement('div');
div.setAttribute('id', 'result');
const content = document.createTextNode(value);
div.appendChild(content);
document.body.appendChild(div);
}
</script>
</head>
<body>
<input type="file" name="document" onchange="checkFileFunction(this.value);">
</body>
</html>
Next we have this simple Selenium program that sends a file path to the file input element and then waits for up to 3 seconds (with the call to driver.implicitly_wait(3)) for an element with an id value of 'result' to be found on the current page and then prints out the text value. This element will only exist if the onchange event occurs:
from selenium import webdriver
options = webdriver.ChromeOptions()
options.add_argument("headless")
options.add_experimental_option('excludeSwitches', ['enable-logging'])
driver = webdriver.Chrome(options=options)
try:
# Wait up to 3 seconds for an element to appear
driver.implicitly_wait(3)
driver.get('http://localhost/test.html')
file_field = driver.find_element_by_name("document")
file_field.clear()
file_field.send_keys(r'C:\Util\chromedriver_win32.zip')
result = driver.find_element_by_id('result')
print(result.text)
finally:
driver.quit()
Prints:
C:\Util\chromedriver_win32.zip
Now if your driver is different and that is the reason why the onchange event is not occurring and you do not wish to or cannot switch to the lastest ChromeDriver, then you can manually execute the function specified by the onchange argument. In this version of the HTML file, I have not specified the onchange argument to simulate the situation where specifying it has no effect:
File test.html Version 2
<!doctype html>
<html>
<head>
<title>Test</title>
<meta name=viewport content="width=device-width,initial-scale=1">
<meta charset="utf-8">
<script>
function checkFileFunction(value)
{
const div = document.createElement('div');
div.setAttribute('id', 'result');
const content = document.createTextNode(value);
div.appendChild(content);
document.body.appendChild(div);
}
</script>
</head>
<body>
<input type="file" name="document">
</body>
</html>
And the new Selenium code:
from selenium import webdriver
options = webdriver.ChromeOptions()
options.add_argument("headless")
options.add_experimental_option('excludeSwitches', ['enable-logging'])
driver = webdriver.Chrome(options=options)
try:
# Wait up to 3 seconds for an element to appear
driver.implicitly_wait(3)
driver.get('http://localhost/test.html')
file_field = driver.find_element_by_name("document")
file_field.clear()
file_path = r'C:\Util\chromedriver_win32.zip'
file_field.send_keys(file_path)
# Force execution of the onchange event function:
driver.execute_script(f"checkFileFunction('{file_path}');")
result = driver.find_element_by_id('result')
print(result.text)
finally:
driver.quit()
Update
I guess you missed <script src="/static/js/jquery.js"> in the <head> section, which appears to be jQuery. But I would have thought that with this script tag being in the <head> section that jQuery would have to be loaded by time Selenium found the file element. So I confess that your getting a javascript error: $ is not defined is somewhat surprising. I can only suggest now that you try loading it manually as follows as detailed in the code below.
I have re-iterated the 3 things you should try in order in the code below moving on to the next approach if the previous one does not work:
Give jQuery time to load before sending keystrokes to eliminate the $ not defined error.
Manually loading jQuery before sending keystrokes.
Manually executing the checkFileFunction.
# 1. Give jQuery time to load before sending keystrokes:
import time
time.sleep(3)
# 2. if the above sleeping does not work,
# remove the above call to sleep and manually load jQuery.
# Specify where the home page would be loaded from:
document_path = '/home/usr/account/public_html' # for example
jQuery_path = document_path = '/static/js/jQuery.js'
with open(jQuery_path, 'r') as f:
jQuery_js = f.read()
self.driver.execute_script(jQuery_js)
# Send keystrokes:
file_path = str(path/to/myfile)
file_field.send_keys(file_path)
# 3. Execute the following if the onchange doesn't fire by itself:
self.driver.execute_script(f"checkFileFunction('{file_path}', '/ajax/check_file/');")
As it turns out, the actual problem was that my manual test were done on the Django app served via python manage.py runserver. This calls some hidden Django magic, including collecting the statics files (css, jQuery.js etc.) under the hood.
I now learned that, in order to serve a Django app on a proper server, one needs to first call python manage.py collectstatic. This will generate a static folder in the parent directory, which contains all the static files and also an explicit jQuery.js.
Then, when Selenium is run, it will find that static folder and the jQuery.js file therein. And then, everything works as expected, including onchange.
So the problem was, that this parent static folder was missing, which I never saw because serving the website via python manage.py runserver doesn't need it.

Importing Custom Fonts Flask and Tailwind CSS

I am working on a web application using Flask and Tailwind CSS and can’t import custom fonts. I can build the CSS file but the HTML template isn’t showing the font. How do I get my custom font to import?
I have this in my CSS build file:
#tailwind base;
#tailwind components;
#tailwind utilities;
#font-face {
font-family: 'Grifter';
src: url(../../static/Skyer-Regular.otf);
}
Here is a sample of when I try to use my imported font:
<head>
<link rel="stylesheet" href="{{ url_for('static', filename=’mainStyles.css') }}"/>
</head>
<body class = 'bg-black'>
<div class = "font-pri text-3xl text-center text-white">
Sample Text
</div>
</body>
I had this exact problem a while ago and have a solution that works. I ended up having to link a separate CSS file to each HTML template. Here is an example of what I did. I have my custom font and CSS file in my static folder. gameStyles.css is my Tailwind CSS file.
<link rel="stylesheet" href="{{ url_for('static', filename='gameStyles.css') }}"/>
<link rel="stylesheet" href="{{ url_for('static', filename='styles2.css') }}"/>
Here is an example of what I would put in styles2.css:
#font-face {
font-family: 'reg';
src: url(../static/ObjectSans-Regular.otf);
}
body {
font-family: 'reg';
}
I tried everything and this was the only thing that worked for me. Hopefully this helps!

Using Vue.js and Flask together

I had code that worked perfectly fine, then I wanted to use flask, so I copied it into a flask app directory. The html code is below:
<html>
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO"
crossorigin="anonymous">
</head>
<body>
<div id="app" class="container">
<div class="row">
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item" v-for="tab in tabs" v-bind:class="tab.active">
{{ tab.name }}
</li>
</ul>
</div>
</nav>
</div>
<div class="row">
<div class="col">
<hr class="navbarDivide">
</div>
</div>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49"
crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="/static/js/challenges.js"></script>
</body>
</html>
When I remove the stuff for Vue, it works perfectly fine (when I remove the v-for, v-bind, and {{ tab.name }}. However, when I add it, it gives me a 500 error. I'm doing all of this using flask. Flask code below:
from flask import Flask, render_template
app = Flask(__name__)
application = app
#app.route('/base')
def index():
return render_template('base.html')
if __name__ == '__main__':
app.run(debug=True)
The javascript code just has the required stuff for Vue.js (the object with the data). The javascript code is below:
var app = new Vue({
el: '#app',
data: {
tabs: [
{ name: "Home", active: "" },
{ name: "Challenges", active: "active" },
{ name: "Scoreboard", active: "" },
{ name: "About", active: "" }
]
}
});
Update:
After a little more debugging, I think I may have figured out the problem. When I comment out all the stuff, and add console.log("it works"); to my javascript code, nothing happens. That probably means the javascript code isn't connecting to the html, but how can I solve that?
I found the solution. I was manually putting the url of the javascript
<script src="/static/js/challenges.js"></script>
What I had to do to fix it was use url_for
<script src="{{ url_for('static', filename='js/challenges.js') }}"></script>
Probably something a lot of people that have used flask before know, but I'm new to this.

Access to valid youtube link is denied after being parsed with Projekktor

I have this html file, downloaded from Projekktor:
<!DOCTYPE HTML>
<html>
<head>
<title>Projekktor Version 8 Test</title>
<link rel="stylesheet" href="theme/style.css" type="text/css" media="screen" />
<script type="text/javascript" src="projekktor/jquery.min.js"></script> <!-- Load jquery -->
<script type="text/javascript" src="projekktor/projekktor.min.js"></script> <!-- load projekktor -->
</head>
<body>
<video id="player_a" class="projekktor" poster="intro.png" title="this is projekktor" width="640" height="360" controls>
<source src="" />
</video>
<script type="text/javascript">
$(document).ready(function() {
projekktor('#player_a', {
volume: 0.8,
playerFlashMP4: 'http://www.localhost:8000/StrobeMediaPlayback.swf',
playerFlashMP3: 'http://www.localhost:8000/StrobeMediaPlayback.swf'
});
});
</script>
</body>
</html>
Then I am obtaining the url for an youtube video via an API call (I have credentials), in order to replace src=''with the result form the following code
import lxml.html as LH
link = youtube_call(id)
def parse_html(link):
filename = 'projekktor.html'
f = LH.parse(filename)
for el in f.iter('video'):
el.attrib['src'] = link
# have also tried
# el.attrib['src'] = link.replace('amp;', '')
new_html = LH.tostring(f, pretty_print=True)
print (new_html)
but when I print it, a nasty amp; is added to src=, and access to link is denied. ( I broke the link here into newlines for readability purposes)
https://r3---sn-oxunxg8pjvn-bpbs.googlevideo.com/videoplayback?expire=1485418386&
amp;mv=m&
amp;mt=1485396620&
amp;ms=au&
amp;clen=13475559&
amp;mn=sn-oxunxg8pjvn-bpbs&
amp;mm=31&
amp;ipbits=0&
amp;requiressl=yes&
amp;itag=18&id=o-AG-dux-Jvtia_DsWZcyRfNpbMlzulsNn6I3SXyi0SI1B&
amp;lmt=1458188966300704&
amp;signature=BDC946187F74386CE00C5452CD703F9B13E4E30F.766549AB6A7C1811899CCC04742353B5BD0153D7&dur=266.448&key=yt6&
amp;ip=177.142.138.140&
amp;sparams=clen%2Cdur%2Cei%2Cgir%2Cid%2Cinitcwndbps%2Cip%2Cipbits%2Citag%2Clmt%2Cmime%2Cmm%2Cmn%2Cms%2Cmv%2Cpl%2Cratebypass%2Crequiressl%2Csource%2Cupn%2Cexpire&
amp;ei=MluJWO_aEIr_-AXHx6GwDA&
amp;mime=video%2Fmp4&
amp;upn=aFGwEwwIS1o&pl=20&source=youtube&
amp;ratebypass=yes&initcwndbps=1178750&
amp;gir=yes
Remove all amp; and the link is valid, but I've tried link.replace('amp;', '') does not work.
Is there any workaround this?

Categories