Picture wont load into div when using Flask - python

I am creating a single page application but my #mainPicture will not load in the div its suppose to. This is where I am calling it in my index.html:
<body>
<div id="mainPicture">
<div class="picture">
<div id="headerTitle">Places I've Been</div>
<div id="headerSubtext">A Blog About My Travels</div>
</div>
</div>
This is my code for linking stylesheet:
<link rel= "stylesheet" type= "text/css" href= "{{ url_for('static', filename='css/theme.css') }}">
And this is the CSS for it in my theme.css:
#mainPicture
{
width:670px;
height:497px;
background-color:#FFFFFF;
}
#mainPicture.picture
{
position:relative;
width:650px;
height:487px;
top:10px;
background-image:url(hudson1.jpg);
background-repeat:no-repeat;
margin-left:10px;
}
It just shows up as a white space the size of the picture. I am using CMDER to run my webpage. The image hudson1.jpg is in the same folder as the theme.css also but it wont show it up in the div.
Any help would be great.

Your selector is incorrect.
#mainPicture.picture
Is looking for an element with id mainPicture and class picture. You should use:
#mainPicture > .picture
That will select the an element with a class of picture that is a child of an element with an id of mainPicture.

Related

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.

How to move an icon?

Code runs fine what am trying to get done is to move the Facebook icon on left of the screen instead of the middle of the screen how could I do that?
import React from 'react';
import { Link } from 'react-router-dom';
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome'
import { faFacebook } from '#fortawesome/free-brands-svg-icons'
function Header() {
return (
<div>
<header className="header">
<div className="col1"><FontAwesomeIcon icon={faFacebook}/></div>
<div className="col2">
<div className="menu">
<Link to="/about"><h3>About</h3></Link>
<Link to="/car"><h3>Cars</h3></Link>
<Link to="/contact"><h3>Contact</h3></Link>
<Link to="/search"><h3>Search</h3></Link>
<nav/>
</div>
</div>
</header>
</div>
);
}
export default Header;
try applying float: left on div which contains the icon.

Difference in css outcome between static and jinja2 html

I am using Flask and therefore Jinja2 to dynamically create a web page.
When I use the render_template function the resulting web pages pick up my css styles normally and do as I expect with some strange exceptions.
For example, the following css and html code is working 100% as intended:
CSS:
.intro {
font-family: monospace;
font-size: 24px;
color: #455934;
padding-top: 30px;
padding-right: 50px;
padding-bottom: 5px;
padding-left: 50px;
}
HTML:
<p class ='intro'>
Hello
</p>
However when using a ``Jinja2``` template:
<p class ='intro'>
{{title}}
</p>
The css style for this class is ignored.
This is not true for any other styles in the same css file and template, for reference the whole template looks like this and the styles for div containers, background, etc. work as intended:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel= "stylesheet" type= "text/css" href= "{{ url_for('static',filename='gemuese_style.css') }}">
<title>{{title}}</title>
</head>
<body>
<div class="outer">
<div class="middle">
<div class="inner">
<p class ='intro'>
{{title}}
</p>
<ul>
<li>{{result}}</a></li>
</ul>
</div>
</div>
</div>
</body>
</html>
Edit:
Some testing has shown me that the style seems to work depending on the variable jinja renders. The template is rendered based on the output of different functions who generally return a list of a string and another list. The string is then used to fill in the {{title}} part where the css is failing.
For some functions it does work but I am not sure why because there is no difference in the return format.
Edit2:
Look at the difference between This rendered template and this one.

How do I add a background image for a div container?

So I am having a bit of trouble inserting an image inside of a div container. At the top of my page I have a fixed navbar and, underneath the navbar, I have a jumbotron div with a div container with the name of the company as well as the tagline. Instead of there being a bg color for the div jumbotron/div container, I would like there to be an image instead that relates to the services and products that are being provided.
I am using Python Django to create the site and thus am using Jinja to implement static files such as images. Below is the code that I've used that does not work. I would like to be able to implement the image using this same Jinja method of static files rather than url(path to image here)... help?
<div>
<div class="jumbotron">
<div class="container" style="background-image:{% static 'company/img/familypic.jpg' %}">
<center><h2>Whatever Text Here</h2></center>
<center><h4>Whatever Tagline Here</h4></center>
</div>
</div>
</div>
It has to be url('{% static 'company/img/familypic.jpg' %}') for the background-image to show up.
Use
<div class="" style="background-image: url({{ static('company/img/familypic.jpg') }});">

Rendering an iframe from HTML stored in the DB

I have a HTML template that I'm rendering using Django. I'm passing in all the necessary context variables — my_heading is the heading, my_html is the mark-safed html. I'd like to display my_html in the iframe.
<html>
<head>
<title>Iframe Example</title>
</head>
<body>
<p>{% my_heading %}</p>
<iframe name="iframe1" width="600" height="400" src="http://www.yahoo.com" frameborder="yes" scrolling="yes"></iframe>
</body>
</html>
Would you know how to do this? All the examples I've found show the iframe pointing to a URL. I'm god-horrible at HTML and JS. :|
Thanks
Michael Klocker does not answer your question, but the answer he has given is a better solution. You should rather do that.
But to answer you question: You can only pass a url to a IFrame, so if really want to use a IFrame, you need to set up second url+view in django to return my_html as the response. I.e. 2 http requests will happen. 1 for the page containing the IFrame, and 1 request for then contents of the IFrame.
If I understand you correctly, you just want to show the HTML content that you prepared dynamically with Python within the Django template, correct? If that is the case, you do not need an Iframe. Iframes are only necessary if you would like to integrate parts of a different URI (webpage) as a frame (section on your webpage) on your page. Here a sample:
<html>
<head>
<title>Iframe Example</title>
</head>
<body>
<p>{% my_heading %}</p>
<div id="content">{% my_html %}</div>
</body>
</html>
Addition to the above code, base on comment below. Sounds like you want to show an entire page with an Iframe and that this second page comes form another view/url on your box. Then use:
<html>
<head>
<title>Iframe Example</title>
</head>
<body>
<p>{% my_heading %}</p>
<iframe src="URL_TO_MY_2ND_VIEW_IN_DJANGO" width="100%" height="300"></iframe>
</body>
</html>
Iframe explanation on W3Schools
Iframe description on W3C Site
I used this hack to do it. The div is hidden and contains the HTML. The IFrame doesn't point to a location because I don't want any CORS issues. I then inject my HTML into it.
<html>
<head>
<title>Iframe Example</title>
</head>
<body>
<p>{% my_heading %}</p>
<iframe name="iframe2" id="iframe2" width="0" height="0" src="" style="border:0px; overflow-x:hidden;"></iframe>
<div id="page" style="display:none" >{{ my_html }}</div>
<script type="text/javascript">
function getWindow(iframe) {
return (iframe.contentWindow) ? iframe.contentWindow : (iframe.contentDocument.document) ? iframe.contentDocument.document : iframe.contentDocument;
}
getWindow(document.getElementById('iframe2')).document.open();
getWindow(document.getElementById('iframe2')).document.write(document.getElementById('page').innerHTML);
getWindow(document.getElementById('iframe2')).document.close();
document.getElementById('iframe2').style.height = (getWindow(document.getElementById('iframe2')).document.body.scrollHeight + 20) +"px";
document.getElementById('iframe2').style.width = (document.getElementById('iframe2').parentNode.offsetWidth) +"px";
</script>
</body>
</html>

Categories