How to Avoid multi post request by one click? - django

I have a simple form which adds personal information of a family. sometime it saves two instance of a person just by one submit. Maybe my mouse has problem and and double clicks instead of one click (it has some problems). I think this is not possible and django accepts just one post request from an instance of a form and not more (maybe it accepts). what if may code has problem? if it is problem of my code, why it happens once a while?
house = get_object_or_404(House, id=code)
if request.method == 'POST':
form = ParentForm(request.POST)
if form.is_valid():
# save it if it's valid
parent = form.save(commit=False)
if parent.living == 0:
parent.in_family = 0
if not parent.guardian:
parent.save()
if parent.guardian and parent.in_family:
parent.save()
I use Django 1.8
Edit to clear: this is not the only view sometime saves twice. Maybe it is a bug in django

To solve this problem, first you need to create unique constraint on the corresponding database table. The real solution is based on the database schema. I don't know what fields (columns) you have in the parent table, you can start from add unique constraint to these two fields: child_id and parent_name.
The other problem is you need to prevent the second click. So basically you need to write some JavaScript code: it listens to the onClick event of the submit button. Once the button get clicked, the listener sets the disabled attribute to that button to prevent further clicks.

Related

Django function execution

In views, I have a function defined which is executed when the user submits the form online. After the form submission there are some database transactions that I perform and then based on the existing data in the database API's are triggered:
triggerapi():
execute API to send Email to the user and the administrator about
the submitted form
def databasetransactions():
check the data in the submitted form with the data in DB
if the last data submitted by the user is before 10 mins or more:
triggerapi()
def formsubmitted(request):
save the user input in variables
Databasetransactions()
save the data from the submitted form in the DB
In the above case, the user clicks on submit button 2 times in less than 5 milliseond duration. So 2 parallel data starts to process and both trigger Email which is not the desired behavior.
Is there a way to avoid this ? So that for a user session, the application should only accept the data once all the older data processing is completed ?
Since we are talking in pseudo-code, one way could be to use a singleton pattern for triggerapi() and return Not Allowed in case it is already istantiated.
There are multiple ways to solve this issue.
One of them would be to create a new session variable
request.session['activetransaction'] = True
This would however require you to pass request, unless it is already passed and we got a changed code portion. You can also add an instance/ class flag for it in the same way and check with it.
Another way, which might work if you need those submissions handled after the previous one, you can always add a while request.session['activetransaction']: and do the handling afterwards.
def formsubmitted(request):
if 'activetransaction' not in request.session or not request.session['activetransaction']:
request.session['activetransaction'] = True
# save the user input in variables
Databasetransactions()
# save the data from the submitted form in the DB
request.session['activetransaction'] = False
...

Django - Create new object in Form, update select box and save it

I think what I'm trying to achieve is not hard, but I have no clue how to do it hehehehe !
Basically what I need is the feature that we have in Django Admin, when you are creating a new object, if you have a Foreign Key, you can add new data (opening a pop-up), save it and then the select box updates automatically.
What I have is this form:
I know that would be easy to do it with some Javascript, but my point is, Django has some rules, and as far I know, I can't add new data to a form already created, right? Otherwise Django won't validate this form. How could I achieve this?
PS: "Local" is the select box where I want to add new data. The user should be able to create a new Local on this page, instead of going to another page to do it. Thanks :)
Here your question:
I can't add new data to a form already created, right? Otherwise Django won't validate this form. How could I achieve this?
Then the answer:
you are right, django will check values match form value rules. But:
realize that your main form is invoked for twice: on GET and on POST. Between both form executions you make changes on database values trhough your new form. That means that in second main form invocation the value added to database is available:
field1 = forms.ModelChoiceField(queryset= ***1*** )
***1***: on second invocation new value is already available on field1.
Then, you don't should to be afraid about this subject, the new value will be available on form on your main form POST request.
Nothing wrong with updating the value using javascript as long the key in your new combo box has the right key in the database then it should be ok.
Call this function after you saved the last entry.
function refreshLocal(){
$.get(window.location.href, '', function(html){
// change the id to the local combox's id
var serverLocalDropBox = $(html).find('#id_local');
if (serverLocalDropBox.length){
$('#id_local').replaceWith(serverLocalDropBox);
}
})
}
If you don't want to use javascript solution, you can post the form with refresh flag and on the server side if you see that flag just don't validate and return the form as is. Since you have a new entry in the foreignkey it will automatically update the queryset to include the new entry.
function serverRefreshLocal(){
var $form = $('#your_form_id');
$form.append('<input type="hidden" name="refresh" value="true" />');
// you can use ajax submit and ajax refresh here if you don't want to leave the page
$form.submit();
}
// Server Side
def your_form_post_view(request):
if request.POST.get('refresh', 'false') == 'true':
# initial is the trick to save user input
your_form = YourForm(initial=request.POST)
context = {
'form': your_form,
}
return render(request, 'your_template.html', context)
# your view code goes here

Django - how to redirect from to another basic on first forms choices

I would like to write simple app in which i'd like to have workflow :
1) user answers form "A"
2) basic on answer of qustion A.a redirect to form "B" or to form "C"
3) save whole instance
All three forms will use the same model (leaving unused fiels as blank).
What is the best way - to save instance partialy and redirect to next forms using for example primary key parameter or push "partialy" answered form to the next form and then save all at once.
How should i redirect ? set success_url of A to a view which, based on POST A.a redirects me the another form ?
Are you sure that you have only one instance?
I would try to refactor it using 3 instances.
If this is not possible, I would store the partial entity in the user session and save at the last step (B or C).
As for the redirect, if you are using the Class Based Views, take a look at form_valid method: it receives the (already validated) form and you just need to save it and redirect.
This is an awesome reference to Class Based Views.

Django. Add selection flags each list item

Good day! I have the object list in admins's cabinet, I must add the flag in front of each item to select (True / False), for example, on this picture
How do I make this with standard methods of Django?
In my case, i have page, for example
I must create checkbox for multichoice and action
You just need to add at least one action. Standard "delete_selected" apparently removed.
class FakeAdmin(admin.ModelAdmin):
actions = ['fake_action']
def fake_action(self, request, queryset):
queryset.update()

Django Processing Form to other Form

I have a view that is an input form that people input their information in (name, address, that sort of thing). They will then click an "ok" button.
After people click "ok" I want them to be redirected to a page that has a table with their inputted information.
Any ideas on how to do this?
So far, I have the first view. When clicking OK all the information is stored in a database. I just don't know how to use it from there.
Note: ModelForms are used
If you look carefully the documentation : https://docs.djangoproject.com/en/dev/topics/forms/#processing-the-data-from-a-form
You could understand that, once you have treated (is_valid() - cleaned_data['']), you have to do a call to
render_to_response('template',{ 'name':name, 'last_name':last_name..}, context_instance=RequestContext(request))
And, in the template called, just make the data you need be shown, as usual..
you could try to pass your newly created object to the next view (which shows the new object) like this, the called view just has to accept your object as parameter.
# ... your form processing here
if form.is_valid():
# create and save your object code here
your_object.save()
return redirect('show_new_data_view', your_object=your_object)
Hope this helps.