Browser (firefox) keeps loading for long django processes - django

I am using django to perform some activity which takes quite a long time to finish ( around 2-3 hrs).
A django form is filled by the user and submitted to initiate the activity.
The view function does all the required functionality but when everything is finished, a HttpResponse is returned to tell the user that the activity is completed.
The problem is that while the process has been completed in the back-end, my browser(firefox) still keeps on loading instead of display the returned HttpResponse.
Can anyone advice me whether it is a browser issue or something wrong in my code.
views.py
def test(request) :
if request.method == 'POST': # If the form has been submitted...
form = TestForm(request.POST)
if form.is_valid(): # All validation rules pass
form_data = form.cleaned_data
## Get the form data and use it
output, error = executeCommand("##Perform the required action with the form data")
if error == '' :
return HttpResponse('Work Done !! Thanks')
else :
return HttpResponse('Error Occurred')
else:
form = TesForm() # An unbound form
return render_to_response("test.html", { 'form' : form } , context_instance=RequestContext(request))

Use celery to pass the job off to the backend for processing

Related

Ensuring Users Have Completed Prior Form Before Progressing To The Next Form

Ive got a large questionnaire for users to complete. Because its so big I decided to break it into three separate forms on three consecutive pages.
The urls are: questionnaire/section_1, questionnaire/section_2, questionnaire/section_3.
After submitting each form, the form data is saved to the database, and after the final (3rd) form, the three forms are saved as a single pdf for that user. Its important that users complete each of the three questionnaires.
My problem is that users will be able to use the address bar to type www.website/questionnaire/section_3 and complete just the third section, skipping the first two and submitting an incomplete questionnaire.
I cant think of any way to restrict users from accessing later parts of the form until prior parts have been successfully validated and saved.
PS - I have thought about setting permission for each of the three forms, adding permissions to the user once they have submitted one form, but I feel this is hacky??
Thank you.
This is the way I ended up dealing with this.
#allowed_users(allowed_roles=['admin', 'registered_user'])
def page_two(request):
if request.method == 'POST':
form = FormTwoForm(request.POST, request.FILES, instance=request.user.formtwo)
if form.is_valid():
form.save()
return redirect('page_three')
else:
# redirect if user didnt access the page from personal_information
if(request.META.get('HTTP_REFERER') != request.build_absolute_uri(reverse('form_one'))):
return redirect('form_one')
else:
form = FormTwoForm(instance=request.user.formtwo)
context = {
'form' : form
}
return render(request, 'example/form_two.html', context)
#allowed_users(allowed_roles=['admin', 'registered_user'])
def form_three(request):
if request.method == 'POST':
form = FormThreeForm(request.POST, request.FILES, instance=request.user.formthree)
if form.is_valid():
form.save()
return redirect('form_four')
else:
# redirect if user didnt access the page from needs_analysis
if(request.META.get('HTTP_REFERER') != request.build_absolute_uri(reverse('form_two'))):
return redirect('form_two')
form = FormThreeForm(instance=request.user.formthree)
context = {
'form' : form
}
return render(request, 'example/form_four.html', context)

How can I delete form field data in django after submit

I'm working on a django project where during registration, a user can submit a code to get special discounts. The validation of the discount codes is already working nicely, but I'm missing one beautifying aspect: After the user submits an invalid code I want to empty out the input field; i.e.:
def validate_code(value):
# check code for validity or raise ValidationError
class CodeForm(forms.Form):
code = forms.CharField(validators=[validate_code])
# in my views.py
def code_verification_view(request):
if request.method == 'POST':
form = CodeForm(request.POST)
if form.is_valid():
# proceed with given code
else:
# modify form to return an empty html input for the code field
# this is where I'm stuck
form.fields['code'].value = ''
# ... render the form in a template
The end result should be a form with an empty input field, but the validation errors showing. The behavior should be similar to how password input fields are emptied if the form verification fails.
EDIT: I solved the problem, but in a very hacky way:
see https://stackoverflow.com/a/46564834/8572938
I'd appreciate a proper solution that does not rely on accessing protected members of the form.
the key is to reset form variable
form = CodeForm(None)
in your code
def code_verification_view(request):
if request.method == 'POST':
form = CodeForm(request.POST)
if form.is_valid():
# proceed with given code
else:
form = CodeForm(None)
Just render your template, if your form is not valid, it will show error, In case if it is valid process your data
def code_verification_view(request):
if request.method == 'POST':
form = CodeForm(request.POST)
if form.is_valid():
// process your data
else:
form.data['field'] = None
return render(request, template_name, {'form': form})
Make a field validation in your form definition:
class CodeForm(forms.Form):
code = forms.CharField(validators=[validate_code])
def clean_code(self):
code = self.cleaned_data(code)
error = # some of your process
if error:
self.fields['code'] = None
raise forms.ValidationError('...')
else:
return code
And remove the else part in your view, instead you want to do something else. If you just want to display the form with error, the raise forms.ValidationError will do it.
You can in django form add a clean_<field_name> to control each field as you like.
More info here
I found a way that works, but it's quite dirty:
old_form = CodeForm(request.POST)
form = CodeForm()
if old_form.is_valid():
# ...
else:
form._errors = old_form._errors
# pass form into the rendering context
This way, I get a clean form with the preserved errors.
While it does the job, it is clearly an ugly hack.

Can't figure out why form.has_changed() is always true?

I'm trying to learn Django and have come up with a situation I can't figure out. I have the following code:
def contact_add(request):
if request.method == 'POST':
form = ContactManageForm(request.POST)
if form.is_valid():
if form.has_changed(): # <-- ALWAYS RETURNS TRUE!
form.clean()
...
elif 'id' in request.GET: # Request to show an existing contact
new_contact_dynamic = contacts.models.PersonDynamic.objects.get(person_static = request.GET['id'],
current_record_fg = True)
form = ContactManageForm(new_contact_dynamic.__dict__, initial=new_contact_dynamic.__dict__)
else: # This must be to add a new contact
form = ContactAddForm()
return render(request, 'contact_manage.html', {'form': form})
So, if I'm sent an ID number, I read a record and display it on the screen. My template gives the user a 'submit changes' button. My problem, as noted above, is that Django always shows that the form has changed, even if the user hasn't changed any data on the screen (i.e. he just hit the submit changes button without changing anything).
So, am I doing something obviously wrong in my code that's creating this situation? Am I misinterpreting how the form.has_changed() method works?
It's my assumption that when I use the initial=parameter after a GET request, Django is storing that data somewhere and knows the context when the user then hits the 'submit data' button, is this wrong?
Yes you need to initialize your Form with initial data.
In your view the GET and POST requests have no common context. You may want to use sessions for that.
But in this case, it is not necessary. You can retrieve the instance on each request:
def contact_add(request):
if 'id' in request.GET:
new_contact_dynamic = contacts.models.PersonDynamic.objects.get(
person_static = request.GET['id'],
current_record_fg = True
)
if request.method == 'POST':
form = ContactManageForm(request.POST, initial=new_contact_dynamic.__dict__)
...
else: # Show an existing contact
form = ContactManageForm(initial=new_contact_dynamic.__dict__)
else:
form = ContactAddForm()
return render(request, 'contact_manage.html', {'form': form})

Django raise Validationerror leads to Valuetype Error

I have tried to do a type check on file uploaded by the user using the clean_field function inside the RegistrationForm class. The Validation part is working well and the redirection works only when a .kml file is uploaded. But the problem occurs when I try to upload a Non KML file. The raise ValidationError does not seem to work. Instead the following error is displayed on the browser.
ValueError at /startanalysis/
The view aerial_analysis.views.second_page didn't return an HttpResponse object.It returned None instead.
Here is my forms file
class RegistrationForm(forms.Form):
resolution = forms.IntegerField(label='Enter required resolution : ')
kml = forms.FileField(label='Enter File : ')
CHOICES = (('1' , '1'), ('2', '2'))
field = forms.ChoiceField(label='Type of analysis :',choices=CHOICES)
def clean_kml (self):
if not self.cleaned_data['kml'].name.endswith('.kml'):
raise ValidationError("Please Upload a Valid KML File")
return self.cleaned_data['kml']
Here is my View Method for this page
def second_page(request):
if request.method == 'POST':
form = RegistrationForm(request.POST,request.FILES)
if form.is_valid():
return HttpResponseRedirect('/main')
else:
form = RegistrationForm()
return render(request, "secondpage.html", {'head_title': 'Head','form1': form,})
I want the browser to just display the error message on the form field. I am quite new to Django, so I might be missing an important part. Any kind of help would be much appreciated. Thank You :)
The problem is here:
if request.method == 'POST':
form = RegistrationForm(request.POST,request.FILES)
if form.is_valid():
return HttpResponseRedirect('/main')
When you're uploading a non KML file, the request.method is still POST. However, since the form raises ValidationError, the form.is_valid() is False. You don't have any logic for that scenario. So the view functions returns None instead of any HttpResponse object.
You need to add another else block here where you render the same form again. This time along with the form field, you should also display the errors (the error message would contain the argument you passed to ValidationError).
So may be add something like this in that else block:
return render(request, "secondpage.html", {'head_title': 'Head','form1': form,})
(Just like your normal get request)

django - redisplay a form after postback but as unbound

Still new to python and django, though learning ;-)
I have a view that is intended to display a form with contact information. After succesfully processing the form and saving/creating the object, I want to display the same view again (to add another contact) but with a message added saying the previous contact information was successfully saved.
From Django return redirect() with parameters I learned that the way to redirect to a view with a passed parameter is to simply call the view again and display the response.
My view starts as follows:
def addabentry(request, entrytype, messages=[]):
""" Presents form to create a company listing, then enters company into database"""
After postback and successfully saving the data, I call the view again as follows:
messages = ["%s %s has been added." % (entrytype, entry.name)]
response = addabentry(request, entrytype=entrytype, messages=messages)
return HttpResponse(response)
However, the form on the second go-round seems to be bound with the previous data, presumably because the POST parameter is still in the request object I pass to the view.
Is there a way to unbind the form for the second time around? Or, as is more likely, is there a better way of doing what I want? Do I need to use request.sessions as mentioned in the referenced SO question?
Thanks for your help!
W.
You need messages framework.
i think you may be making things a lot more complicated than they need to.
from the basic form example in the docs
def contact(request):
message = ''
if request.method == 'POST': # If the form has been submitted...
form = ContactForm(request.POST) # A form bound to the POST data
if form.is_valid(): # All validation rules pass
# Process the data in form.cleaned_data
# ...
# instead of redirecting here, create a new blank form, and add a message
form = ContactForm()
message = "contact successfully created"
else:
form = ContactForm() # An unbound form
return render_to_response('contact.html', {
'form': form,
'message': message,
})