Upload and process a file in a MaterializeCSS form with Selenium - python

Html of the form:
<form action="" method="post" enctype="multipart/form-data"><input type="hidden" name="csrfmiddlewaretoken" value="nTfw60C2FSwLfGTvOlO6FITRnz4yq2HObLpcDw1enoqaT9JsD4ztaDJpCpBVBpS7">
<div class="file-field input-field">
<div class="btn">
<input type="file" name="uploaded" id="id_uploaded">
<span>Choose file</span>
</div>
<div class="file-path-wrapper">
<input class="file-path validate" type="text" id="id_path">
</div>
</div>
<div class="col s12">
<button class="btn-flat" id="id_submit" type="submit">Submit</button>
</div>
</form>
The problem is that a click on the file text input opens a file dialog and MaterializeCSS doesn't accept pasting a file path string. Also, only the filename without the full path is shown in the text input after a user selects a file in the dialog.
When the following code runs then the form invalidates with my no file provided error:
text_input = webdriver.find_element_by_id("id_path")
text_input.clear()
text_input.send_keys(path_to_file)
webdriver.find_element_by_id("id_submit").click()
Any suggestions on how to solve this problem and provide a file in tests? Any workaround could be an acceptable answer as I just want to test the functionality that takes place after submitting a file.

Related

FLASK app: Sending data from a Form through another script while one "input" is a dynamic paragraph

I have a from with three possible inputs to submit and send through a seperate script that then generates JSON data.
The problem is however while two inputs are actual inputs = one email and one being a nummer. The third one is not a really traditional input.
<form action="{ url_for('handle_data') }}" method="POST">
<div class="form-group">
<label for="Speryear">SPER jaar</label>
<input class="form-control" type="number" value="2" name="Speryear" min=0 max=10 />
</div>
<div class="form-group">
<div class="form-group">
<label for="inputEmail">Verzendings mail</label>
<input class="form-control" type="email" name="inputEmail" required />
</div>
</div>
<div class="form-group">
<div class="url-panel">
<p> <b>Url:</b></p>
<p id="api-url" name="api-url"></p>
</div>
</div>
<button id="search" type="submit" class="btn-primary">
Aanvraag indienen</button>
</form>
#app.route('/handle_data', methods=['POST'])
def handle_data():
sper_year = request.form["Speryear"]
email = request.form["inputEmail"]
url = request.form["api-url"]
Requested_data = GIPOD_converter.main(url, sper_year, email)
return Requested_data
The third input is actually a paragraph which is dynamically based on the values of a second form (the primary from) for the data requests. According to this post here:
Sending data from a html non-input to Flask
HTML forms only send along tagged values to the remote endpoint when a "submit" input is pressed.
I have tried to make this paragraph a data input but the thing is this will break the javascript I have for that specific id. Aka a the URL part that I want cannot be generated in the input field. So can my code get the paragraph from this?
Edits done as per answer.
I think you should end the app route with:
return Requested_data
Also, you do not define correctly to the url form, i.e.:
url = request.form["api-url"]

can you change the way get method makes links for django?

I'm using django for a website that has a searchbar setup with a simple form:
<form method="get" action="/browse">
<div class="input-group col-md-12">
<input type="text" name="searchquery" class="form-control input-lg" placeholder="Search" style="margin-right:1vw; border-radius: 5px;"/>
<span class="input-group-btn">
<button class="btn btn-primary btn-lg" type="submit">
{% fontawesome_icon 'search' color='white' %}
</button>
</span>
</div>
</form>
This creates url's like this:
http://127.0.0.1:8000/browse/?searchquery=<searchquery>
However I've setup my django url like this:
http://127.0.0.1:8000/browse/<searchquery>/
I would like to use the second url (as it just looks a lot better in my opinion).
Is there a way I can make my form do this?
This isn't a question about Django. The browser simply can't do this with an HTML form. The action attribute of the form is set when it is loaded.
You could possibly write some JavaScript to make it do this. But that would be the wrong thing to do. Queries like search should be part of the querystring, not the URL.

Unknown code being added to HTML template when running local server

I was building a profile picture feature, it was working fine so I left it for a while, probably a week. I came back to it and ran the local server, but when I do there's a few lines that appear in the console. But do not exist on the source file.
Source file:
<script type='text/javascript'>
Dropzone.options.myDropzone = {
autoProcessQueue : false,
paramName: 'uploaded_image',
dictDefaultMessage: "Drag and drop files or click here to upload picture",
init: function() {
var submitButton = document.querySelector("#submitBtn")
myDropzone = this;
submitButton.addEventListener("click", function() {
myDropzone.processQueue();
});
// Automatically overwrites file so the user can only upload one
this.on("addedfile", function() {
document.getElementById('submitBtn').style.visibility = "visible";
});
this.on('addedfile', function(){
if (this.files[1]!=null){
this.removeFile(this.files[0]);
}
});
}
};
</script>
<!-- Modal -->
<div id="picModal" class="modal">
<!-- Modal content -->
<div class="modal-content">
<span class="close"></span>
<form action="{% url 'profile_test' %}" method='POST' enctype="multipart/form-data" class="dropzone" id="my-dropzone">{% csrf_token %}
<!-- submit button stays hidden by default, until user selects a picture -->
<button id='submitBtn' type='submit' class='pic-submit-button' style='visibility: hidden;'> Submit </button>
<input id='submit-all' type='file' name='uploaded_image'/>
{{form}}
</form>
</div>
</div>
Now the code I'm seeing when I run the server is only a few lines, and it's in the HTML that creates the modal:
<!-- Modal -->
<div id="picModal" class="modal" style="display: block;">
<!-- Modal content -->
<div class="modal-content">
<span class="close"></span>
<form action="/api/profile_test/" method="POST" enctype="multipart/form-data" class="dropzone dz-clickable" id="my-dropzone"><input type="hidden" name="csrfmiddlewaretoken" value="WDMihPq0zDhDQGaWxSFYyvxjtmxUxsBMpAzcDqVxDGUZj11O8wtqbCfCie1m81Tf">
<!-- submit button stays hidden by default, until user selects a picture -->
<button id="submitBtn" type="submit" class="pic-submit-button" style="visibility: hidden;"> Submit </button>
*****<input id="submit-all" type="file" name="uploaded_image">
<label for="id_user">User:</label><select name="user" id="id_user">
<option value="" selected="">---------</option>
<option value="2">Brian</option>
<option value="3">Charles</option>
</select>
<label for="id_img">Img:</label><input type="file" name="img" required="" id="id_img">
<div class="dz-default dz-message"><span>Drag and drop files or click here to upload picture</span></div></form>
</div>
</div>*****
The last chunk of code I put stars around is the code that is unknown to me. The Django project I cloned was using gulp, I talked to my friends and they said that it may have something to do with it, maybe it's doing something with Dropzone.js?. But why would it inject a random dropdown menu listing users in Django? I didn't use gulp myself because I just wanted to develop the feature, but that may have been a mistake.
Possibly the
{{form}}
is causing this issue.

Serve a file based on request parameters in tornado

The problem looks simple but everywhere I search it I get results for uploading a file, whereas my use case is, that based on a few params, I in my Handler decide the relevant file and upload it as a link in my View. I am using tornado for this. e.g :
<div class="form-group"> <!-- Date input -->
<label for="actDateFrom" class="control-label">Date</label>
<input ng-model="data.actDateFrom" class="form-control" name="actDateFrom" placeholder="MM/DD/YYY" type="text"/>
</div>
<div class="form-group"> <!-- Date input -->
<label for="actDateTo" class="control-label">Date</label>
<input ng-model="data.actDateTo" class="form-control" name="actDateTo" placeholder="MM/DD/YYY" type="text"/>
</div>
<div class="form-group"> <!-- Submit button -->
<button type="submit" class="btn btn-default" data-ng-disabled="form.$invalid" data-ng-click="sendActRequest()" >Go Fetch !</button>
</div>
Based on the inputs above, I have a handler, that should basically filter a csv file and get that file showing up as a link .
All I am stuck at is the code for uploading that subset file as a link in my view, I can manage the rest. Please not that the file is lying somewhere on the server itself.
Thanks in Advance!
Lol that was so easy, I think the funda is that only a static file can be served, I just put it in my some web/static/files path which is visible to the server and posted a href link to it, something like below:
<div>
Activations Logs for the time period.
</div>
Please dont downvote, actually I am new to Web Dev :P Thanks !

Reload a csv file and call the same view with it

I have two templates (initial.html and index.html) containing (among others thing) a form. I use data from this form to generate a csv (data.csv) and then read it in the index.html thanks to d3 and parcoords.js. Each new submission generate a new data.csv
The thing is, on the first call, everything seems to work but the moment I try to submit the form with new values the visualization does not change (even if the file data.csv appears to change when I open it with TextEdit)
Moreover, the data (values in main.py ) I provide to the view does not change either.
I know it is not recommended to call the same view after a POST submission but even if I try to call a different view, both of the problems described below remains.
Relevant parts of code are as follows:
main.py
#app.route('/', methods=['POST','GET'])
def main():
global maxDepth
global numberOfRelated
if request.method=='POST':
url = request.form['url']
maxDepth = int(request.form['depth'])
numberOfRelated = int(request.form['numberOfRelated'])
values = crawling(url,maxDepth,numberOfRelated)
return render_template('index.html',var=values)
return render_template('initial.html')
the crawling function
def crawling(url,maxDepth,numberOfRelated):
start = time.time()
initialID = get_id(url)
videosId.append([0,initialID])
getAllID(1,initialID)
getVideoData(videosId)
if os.path.exists('static/csv/data.csv'):
os.remove('static/csv/data.csv')
with open('static/csv/data.csv','wb') as csvData:
dataWriter = csv.writer(csvData, delimiter='|', quotechar='|', quoting=csv.QUOTE_MINIMAL)
dataWriter.writerow(['Depth']+['ID']+['Title']+['Popularity']+['Occurency'])
for x in xrange(0,len(videosData)):
dataWriter.writerow([videosData[x].level]+[videosData[x].id]+[videosData[x].title.encode("utf-8")]+[videosData[x].popularite]+[videosData[x].occurence])
timeExecution = round(time.time() - start,1)
mostFrequent = mostFrequentVideo()
mostPopular = mostPopularVideo()
initialVideo = videosData[0]
return [initialVideo,mostPopular, mostFrequent, len(videosData), timeExecution]
The form
<nav class="navbar formSpace">
<div class="container">
<form class="form-inline" action="" method="POST">
<div class="service form-group">
<i class="fa fa-youtube fa-2x"></i>
</div>
<div class="form-group">
<input type="text" class="form-control" id="mainForm" placeholder="https://www.youtube.com/watch?v=2HIuN5lxMCI" name="url" />
</div>
<div class="form-group minorForm">
<input name='numberOfRelated' type="text" class="form-control" placeholder="Number of suggestion" />
</div>
<div class="form-group minorForm">
<input name='depth' type="text" class="form-control" placeholder="depth" />
</div>
<div class="form-group navbar-right">
<button class="btn btn-success minorForm generate" type="submit"> Generate</button>
</div>
</form>
</div>
</nav>
main.js
var pc0;
var blue_to_brown = d3.scale.linear()
.domain([0, 5])
.range(["red", "#3498db"])
.interpolate(d3.interpolateLab);
d3.csv('static/csv/data.csv?_='+ Math.random(), function(data) {
pc0 = d3.parcoords()("#example0")
.data(data)
.showControlPoints(false)
.hideAxis(["Title"])
.hideAxis(["ID"])
.composite("darker")
.width(860)
.color(function(d) { return blue_to_brown(d['Depth']);})
.render()
.alpha(0.35)
.brushMode("1D-axes")
.reorderable()
.interactive();
});
Flask serves static files that tell the browser to cache the file rather aggressively. The default is to tell the browser to cache the file for 12 hours.
You can bypass this cache by adding a random value to the URL;
d3.csv('static/csv/data.csv?_=' + Math.random(), function(data) {
Now the browser will see this as a new URL each time and not re-use the cached file.
Well, I finally found the solution
The trick advised by Martijn Pieters works perfectly fine, the problem was coming from the format of my CSV. (I was using '|' instead of ',' and D3 didn't like that)

Categories