Django Views - Block Consecutive Quick Calls - python

A button click in my app calls a view which does a few database changes and then redirects to a new views which renders html. When the user typically clicks on the link, he accidentally clicks on in twice to thrice in a couple of seconds. I want to block the view call if the same call was made less than 10 seconds ago. Of course I can do it by checking in the database, but I was hoping to have a faster solution by using some decorator in django.

This should help. It's a JavaScript to disable the button on click, enable it after the operation completes.
$(document).ready(function () {
$("#btn").on("click", function() {
$(this).attr("disabled", "disabled");
doWork(); //this method contains your logic
});
});
function doWork() {
alert("doing work");
//actually this function will do something and when processing is done the button is enabled by removing the 'disabled' attribute
//I use setTimeout so you can see the button can only be clicked once, and can't be clicked again while work is being done
setTimeout('$("#btn").removeAttr("disabled")', 1500);
}
More info here.

You should disable the button with JavaScript after clicking on it.
This way the user is unable to trigger the view multiple times.

No, you can't use decorators in Django to do that.
The methods in your views file are supposed to be telling what to show on your screen. Whereas, the template files are created to tell Django how you want to show them.
You want Django to not count two consecutive calls on same view.
The problem is:
What do you mean by "consecutive"? How fast should I click to make it "non-consecutive"? What if I write a script that does the clicks? How would you define consecutive then?
Even if you did do that above part using some hack, the next problem would be to differentiate between the requests that come from different users (to that view). How would you differentiate between them to determine the "consecutiveness" of a particular user?
Why make unnecessary changes to do all this stuff?
Django is supposed to be used along with other things too. I have learned this the hard way. Using Javascript is the only way to do it, without any problems.
Client-side, one click and poof! disabled. Very fast and you have the request in pool.
Doing this part is easy. Refer to these links for more info:
How to disable html button using JavaScript?
Disable/enable an input with jQuery?

Related

Refreshing page on database modification

In the main page of my website there is a long list, <ul>. Each list item represents a model object. Within the list there are the objects attributes, for example its name etc, and also buttons to change those attributes. The list is loaded from the sqlite database. The issue is since each button changes data in the database, to display the changed data, the view function reloads the page on each button click. That is fine, except the list is very long, and is necessary to scroll down, and on each button click, the page is reloaded therefore goes to the very top of the list. This makes the webpage almost unusable, or at least very annoying to use.
Can someone recommend a workaround to this problem. Please let me know if my question is not clear
It looks like what you want to achieve is something that should be done with Javascript. It will be the simplest way of doing it! For instance, you can call the corresponding API when the user clicks on one of the buttons, and if the API returns 'OK' then you can just update the item with the changes you made (because if the server returned yes, then you can assume that the local version of the data is the same than the one on the server)

How can I click (bypass) a submit button using Python Selenium, when the button gets disabled after using .clear() or .send_keys()?

As the title says, how can I .click() a button using Selenium, when the button gets "disabled" after using the method clear or send_keys?
Before:
That's the page status when I open it's url... but then right after I run my code to find the textbox and replace it's value, the element gets disabled (maybe by some sort of JS) right after I clear it's content or write something to it using send_keys.
After:
Code:
txt_value = driver.find_element_by_xpath('//input[#id="txtValor4"]')
txt_value.clear() #this disables the button
txt_value.send_keys(str(123,45)) #this also disables the button
My question is:
How can I bypass this website protection and press the Continuar button?
I thought about disabling JS, but the whole website relies on it to produces the requires documents.. wrong alternative.
So I thought about using the button properties to simulate the pressing of the button... just don't know if it's possible, or how I could do this.
Another option was blocking only the JS that disables the button maybe mapping where the command comes from using the inspect element and network tools...
So is there any way to achieve this?
ps.: I can't give the URL because it requires my login data.
Ok, so you can't directly do this through normal means. Selenium WebDriver is made to simulate real use of a browser. It may be possible however to use the execute_script function. (Java Selenium has a built in JavascriptExecutor class, I assume this is python's version.) The execute_script function allows Selenium to perform tasks that a human interacting with a browser can't do.
driver.execute_script("document.getElementById('buttonid').click()")
Or something along those lines should work. Hope that helps you out.
If you don't get any solution with selenium and javascript, you can use Sikuli concept. To click that element, take the image of the 'Continuar' button and save it in resources folder.
String elementImg=Path of the Image;
screen.click(elementImg);
I could bypass this using driver.execute_script("document.getElementById('txtValor4').‌​value = 123.45"), to pass the values into the textbox, so the button didn't got disabled and I could press the Continue button.
Even bypassing this, the result wasn't the expected! The value that I entered was supposed to be corrected by some sort of interest. But bypassing this, the value isn't corrected.
Today the user that asked the program told me that everytime I change the value inside this textbox, I must press the Calculate button.
So, instead of inefficiently bypassing this disable method, I could solve my problem using:
b = driver.find_element_by_xpath('//input[#id="txtValor4"]')
b.clear()
b.send_keys('123.45')
driver.find_element_by_xpath('//input[#id="btnCalcular4"]').click()
driver.find_element_by_xpath('//input[#id="btnContinuar4"]').click()
This way the tax value is corrected by interest and the website generate the .pdf with the exact value that I was expecting.
Many thanks for everyone that put some time and effort trying to help me.

pygtk TextView and WebKit.WebView synchronized scrolling

I've got a text view and a web view, each inside a scrolled window of their own and I'm trying to achieve synchronized scrolling between the two but I can't seem to get it to work.
The web view is basically taking the text from the text view and rendering it as marked up HTML via webview.load_html_string(). I think the problem could be the delay in loading the HTML as every time the web view is refreshed it is scrolled back to the very start.
Right now I call a function every time the content of the text view is changed and then modify the vadjustment.value of the scrolled window containing the web view.
But this doesn't work. Is it because of the delay? I can't think of any way to solve this issue.
why do you want sync those scrollbars? You can achieve this by using the same Gtk.Adjustment (number of pages sets to 0).
I haven't use much of webkit but it essentialy a widget. so maybe a workaround would be disconnect a signal "value-changed" from Gtk.Adjustment until "load-status" signal from WebKitView reached Webkit.LoadStatus.FINISHED (if that's the correct syntax).
If that doesn't work, maybe you use WebKitView.move_cursor () (if i remember the function properly) based on Gtk.Adjustment on your text view (we use 2 adjustments this time)

Prevent double submits

I am using GAE for an app that has various submit href buttons, and use javascript to submit.
I am having a real tough time trying to figure out how to prevent multiple submits or doubl-clicking. I have tried various methods to disable or remove the href with javascript.
But I am thinking if there is maybe a method to prevent this in the backend.
What methods would you recommend I use?
Preventing it on the server side is not trivial - a second call may hit a different instance. So you need to deal with sessions. The code will get complex quickly.
I would recommend disabling the button before a call and reenabling it upon a response.
You can use a javascript to disable all submit buttons on your page when a form is submitted. Maybe something like this:
document.forms[0].addEventListener('submit', function() {
var btns = document.querySelectorAll('input[type="submit"]');
for (var i = 0; i < btns.length; i++) {
btns[i].disabled = 'disabled';
}
});
If you need to also disable other elements you can modify the querySelector.

Can I Use Python to Make a Delete Button in a 'web page'

I have written a script that goes through a bunch of files and snips out a portion of the files for further processing. The script creates a new directory and creates new files for each snip that is taken out. I have to now evaluate each of the files that were created to see if it is what I needed. The script also creates an html index file with links to each of the snips. So I can click the hyperlink to see the file, make a note in a spreadsheet to indicate if the file is correct or not and then use the back button in the browser to take me back to the index list.
I was sitting here wondering if I could somehow create a delete button in the browser next to the hyperlink. My thought is I would click the hyperlink, make a judgment about the file and if it is not one I want to keep then when I get back to the main page I just press the delete button and it is gone from the directory.
Does anyone have any idea if this is possible. I am writing this in python but clearly the issue is is there a way to create an htm file with a delete button-I would just use Python to write the commands for the deletion button.
You could make this even simpler by making it all happen in one main page. Instead of having a list of hyperlinks, just have the main page have one frame that loads one of the autocreated pages in it. Put a couple of buttons at the bottom - a "Keep this page" and a "Delete this page." When you click either button, the main page refreshes, this time with the next autocreated page in the frame.
You could make this as a cgi script in your favorite scripting language. You can't just do this in html because an html page only does stuff client-side, and you can only delete files server-side. You will probably need as cgi args the page to show in the frame, and the last page you viewed if the button click was a "delete".
You would have to write the web page in Python. There are many Python web frameworks out there (e.g. Django) that are easy to work with. You could convert your entire scripting framework to a web application that has a worker thread going and crawling through html pages, saving them to a particular location, indexing them for you to see and providing a delete button that calls the system's delete function on the particular file.
Rather than having your script output static HTML files, with a little amount of work you could probably adapt your script to run as a small web application with the help of something like web.py.
You would start your script and point a browser at http://localhost:8080, for instance. The web browser would be your user interface.
To achieve the 'delete' functionality, all you need to do is write some Python that gets executed when a form is submitted to actually perform the deletion.
Well I finally found an answer that achieved what I wanted-I did not want to learn a new language-Python is hard enough given my lack or experience
def OnDelete(self, event):
assert self.current, "invalid delete operation"
try:
os.remove(os.path.join(self.cwd, self.current))

Categories

Resources