I am working on a django application that uses celery to run tasks asynchronously. Right now a user can submit a form from the webpage to start a celery task. But there is no way to pause or stop the task on the click of a button inside a django template.
this is my code so far
celery task
#shared_task
def get_website(website):
website_list = return_website_list(website)
return website_list
In the above task I am calling a return_website_list() function that scrapes the required website and returns a list of links from the website.
output.html template
<div class="container">
<button class="pause_btn" type="button">Pause task</button>
<button class="resume_btn" type="button">Resume task</button>
<button class="stop_btn" type="button">Stop task</button>
</div>
I want the ability to pause the task indefinitely when the pause button is clicked and resume the task when the resume button is clicked or the ability to stop the task completely when the stop button is clicked.
views.py
def index(request):
if request.method == 'POST':
website = request.POST.get('website-name')
get_website.delay(website)
return redirect('output')
return render(request, 'index.html')
I searched online, like these link1, link2, link3. But these links did not help me achieve what I am trying to do.
Thanks in advance
my idea is a field named state and state will set from pause button click. and in celery task in each action check state and if it is in paused state wait for 1 second and check again. i used this idea previously for cancel action
Related
I am trying to write a selenium test for the submission of a form, which uses intercooler.js when it is submitted. The main problem I am having, is that when I navigate to the page, the form has class="disabled", which is not expected behaviour, and I can't submit the form. The relevant part from the intercooler docs says:
By default, intercooler will apply the disabled class to the element
that triggers an intercooler request. This can be used to give a
visual hint to the user that they should not click or otherwise
trigger the request again, and is Bootstrap-friendly.
However, it seems to me that the disabled class is being added to the form element before I actually submit the form, and as I understand it should only be added after a request is in-flight.
The form currently looks like this:
<form ic-post-to="/dashboard/calculate/2/exports/" ic-select-from-response="#content" ic-target="#content" method="post" ic-src="/dashboard/calculate/2/exports/" ic-verb="POST" ic-trigger-on="default" ic-deps="ignore" class="disabled">
<input type="hidden" name="csrfmiddlewaretoken" value="...">
<input type="submit" name="new" value="New" class="btn btn-primary float-right ml-1" id="submit-id-new">
</form>
I have tried adding explicit and implicit waits so that the entire page will load but the problem is still there.
Any help with this would be much appreciated.
Try to use Javascript to click on the button:
submit = driver.find_element_by_id("submit-id-new")
driver.execute_script("arguments[0].click();", submit)
It turns out that I was waiting in the wrong place. Instead of waiting when the page loads, I should have been waiting after the form was submitted to allow the page content to be updated.
I have a Flask site that has a 'search bar' where you type in the location ID of a particular location and then click Submit to be taken to the page for that location, if it exists. Here's the current form action:
<form id="locationinfo" action="{{ url_for('location') }}">
When you click Submit you are taken to /location?info=SITEID and that works just fine. What I want to do is change this behavior slightly so that when a user clicks Submit they are taken to /location/SITEID/ instead. I have the decorator set up in my main Flask routes file, but I'm struggling to put the pieces together to get this simple form together.
#app.route("/location/<locationid>/")
def locations(locationid):
...
return locationid
Any direction would be greatly appreciated!
[Edit with current full form code]
#app.route("/location")
def location():
location_id = request.args.get("info")
<form id="info" action="{{ url_for('location') }}">
<input type="text" name="info" id="locationfield">
<button type="submit">Go!</button>
</form>
You can't change how HTML forms submit their fields, they will always be in the query string or body (POST). One option is to use JavaScript to override the submit event to perform your own submit and re-render with the results.
A simpler solution is to redirect to the nice url after submit. This keeps the "search" action separate from the "show" action (even if they are handled by the same view).
#app.route('/location/')
#app.route('/location/<int:id>/')
def location(id=None):
# redirect to the second form if the id wasn't in the path
# raises 400 error if id wasn't in the query
if id is None:
return redirect(url_for('location', id=request.args['info']))
# id is in the path, continue
...
You can expand this later if you want to search by something besides id. Perform the search then redirect to the found id.
In the process of teaching myself how to use python's tornado web framework, I am trying to create a simple web server and some web pages. On one of the web pages, I have two buttons: one to log users out and redirect them back to the login page and one to submit a blog post. They are both "post" requests and have their name values in html set to "logout" and "new_post".
My questions is, how can I tell which button was pressed so that the post() method for the page's RequestHandler can perform the correct actions in each case? Is there a way to grab the "name" of the button pressed?
When you submit a form with a button click, a parameter with the name of the clicked button gets added to the request.
You can check, if the parameter exists and then do your stuff.
def post(self):
if self.get_argument("logout", None) != None:
# do logout stuff
if self.get_argument("new_post", None) != None:
# do submit a blog post stuff
On Python3 using Tornado, the setup looks as follows with two submit buttons (which is very similar to the above answer).
First the HTML and note both buttons are similar with differing display values. The name parameter is what will be passed to Tornado's POST handler:
<p><input type="submit" class="button" name="basic" value="Basic Query"></p>
<p><input type="submit" class="button" name="advanced" value="Advanced Query"></p>
Next, the POST handler. Using get_argument, you can specify the name and select it if the input is not null. Remember to include the ", None" in get_argument so that it defaults to None should the option not be selected:
def post(self):
if self.get_argument('basic', None) is not None:
self.write('Basic Query')
elif self.get_argument('advanced', None) is not None:
self.write('Advanced Query')
That's it! 2 forms and the ability to differentiate between. Happy coding!
So I'm trying to consider the case where a logged in user has say, 2 tabs open, and logs out of my site in one tab but in the other tab since they're still 'logged in', and they try to click a button which submits POST data, my function in my view should detect that the user is not authenticated and it should redirect them to the login page. However, I can't seem to get this to work at all. I've done numerous testing and I know my condition is getting validated correctly, but the redirect just doesn't happen. Below is the code for the form and the code in my view.
<form method="POST" action="">
{% csrf_token %}
# an input button
</form>
if not request.user.is_authenticated():
return HttpResponseRedirect(reverse('django.contrib.auth.views.login'))
#otherwise I check if it was request.POST etc and handle a normal request
I've tried to hard code the url, using the login url specified in my settings file, etc but none of it seems to do anything. I'm thinking it's all because of the empty action="" part but I don't think that's the reason.
Seems to me like a perfect task for the login_required decorator: https://docs.djangoproject.com/en/1.5/topics/auth/default/#the-login-required-decorator
I'm using Django as the web framework. On a single HTML page, I have a form whose purpose is to start a Python subprocess when I click on its submit button. The fields of the form will be filled with parameters which will be passed to this subprocess.
Now, I want to be able to stop the same subprocess using another form button, preferably within the same form. How can I do this? It's probably not that difficult, but I don't know at the moment how to accomplish that in a simple but elegant way. Any ideas? Thank you very much!
You have to keep a reference to the process in the session. Give each submit button a different "name" attribute, and if this signals stop, kill the subprocess.
from subprocess import Popen
if 'start' in request.POST:
p = Popen("do something")
request.session['myprocess'] = p
elif 'stop' in request.POST:
request.session['myprocess'].kill()
Form:
<form method="POST">
<input type="submit" name="start" value="start"/>
<input type="submit" name="stop" value="stop"/>
</form>
Whether this works depends on your session-storage backend though.