I have a Django form that takes filter options for a report. The report page is a separate view that renders the report based on the form data.
My first pass at this, I simply set the action of the form to the report page and method to GET. The form data was then passed directly the report view via the querystring which I would use GET to retrieve. The problem with this was that this bypassed form validation since the the form did not post back to its own view.
My next pass, I removed the form action (so it would post back to itself) and used form_valid (I am using class based views) to encode the form data and redirect to the report view like so:
ReportOptionsView(FormView)
form_class = OptionsForm
template_name = 'my_report_options.html'
report = reverse_lazy('my_report')
def form_valid(self, form):
qstr = urlencode(form.cleaned_data)
return redirect(self.report+"?"+qstr)
The report page works the same -I just retrieve the information from the querystring to filter the models and display the report.
I would prefer the form data not appear on the querystring of the report page. When I tried to redirect to the report page using a POST method is where I starting having trouble. Even going back to my original flow setting the form action to the report page (thus losing validation) and setting the form method to POST, I got 405 errors. I realize that there may be ways to do this using Javascript, but would prefer to stick with Django/Python
My question is, what is the proper method in Django to take cleaned data from a validated form and POST that data to separate view so that the form data is not exposed in the URL?
Related
I added a Django form to my Bootstrap nav bar to be included on every page, and it renders as it should with the appropriate values. The form was added using an inclusion_tag. However, I'm now at a loss as to how to handle the request from the form. Upon submission, whichever page the user was on should reload with updated content from the form submission. For more context, see my earlier question: How to place a django form in a nav bar so that it appears on every page?
Answering my own question (again). To handle a request from a form that appears on every page and loaded via a custom template tag, create a url path and corresponding view -- e.g. '/form-submission/' and form_submission_view. In the view, handle the form processing logic as you normally would for a POST request, but then return a redirection back to whatever page the user was on when the form was submitted, like so:
return redirect(request.POST.get('path'))
I have a Django form with two dropdown integer fields and a submit button.
A user selects values from these dropdown fields and click on submit button.
The Django template performs a form 'post' and sends these two dropdown values to my Django views.
Django views performs the form validation by validating these two dropdown fields values.
If the form is not valid, it will send the error message to the Django template and I can display the error message on the same form page above the form.
If the form is valid, then it will redirect to a new URL.
Issue: How do I tell my Django view to redirect the URL to a new tab only after the form is valid?
I'm assuming that you're already familiar with Djangos Form View. Within the form_valid(self, form) method of your class based view simply replace return super().form_valid(form) with redirect(reverse('YOUR_TARGET_VIEW')). If you have other mixins within your view that rely on form_valid you may also call super().form_valid(form) prior to returning the redirect reponse but without returning its returned data further.
As of displaying error messages you may refer to the django message framework.
EDIT: A cleaner way to do this, may be to overwrite success_url within your processing but this may not be appropriate to all use cases as you need to provide usefull defaults within each request path.
I am using Boostrap modal fade window which renders Django form to update my database records. And what I fail to do is not to reload the page if the user has opened the Update window and did not change anything. It will be easier to get my idea if you look at the code below:
def updateTask(request, task_id):
#cur_usr_sale_point = PersonUnique.objects.filter(employees__employeeuser__auth_user = request.user.id).values_list('agreementemployees__agreement_unique__sale_point_id',flat=True)
selected_task = Tasks.objects.get(id=task_id)
task_form = TaskForm(instance=selected_task )
taskTable = Tasks.objects.all()
if request.method == 'POST':
task_form = TaskForm(request.POST,instance=selected_task)
if task_form.has_changed():
if task_form.is_valid():
# inside your model instance add each field with the wanted value for it
task_form.save();
return HttpResponseRedirect('/task_list/')
else: # The user did not change any data but I still tell Django to
#reload my page, thus wasting my time.
return HttpResponseRedirect('/task_list/')
return render_to_response('task_management/task_list.html',{'createTask_form':task_form, 'task_id': task_id, 'taskTable': taskTable},context_instance=RequestContext(request))
The question is, is there any way to tell Django to change the url (like it happens after redirecting) but not to load the same page with same data for the second time?
It's not trivial, but the basic steps you need are:
Write some javascript to usurp the form submit button click
Call your ajax function which sends data to "checking" view
Write a "checking" view that will check if form data has changed
If data have changed, submit the form
If not, just stay on page
This blog post is a nice walkthrough of the entire process (though targeted towards a different end result, you'll need to modify the view).
And here are some SO answers that will help with the steps above:
Basically:
$('#your-form-id').on('submit', function(event){
event.preventDefault();
your_ajax_function();
});
Call ajax function on form submit
Gotta do yourself!
Submit form after checking
What I am trying to do I have a view which has a shortcut form which will ask a user to pre-fill some fields before a user is redirected to wizard forms.
For example:
class PreFillView():
def post(self,request):
# get the data from the form and save into request.session
# Then http redirect to the wizard view
Then from this view, I redirect it to a WizardView. In the wizard view, I catch all the information passed in from the previous view in dispatch function:
class MyWizardView(NamedUrlSessionWizardView):
def dispatch(self,request, *args, **kwargs):
#parse data from request.session
#set step data using these data
# Note these data fields only partially covered the form in the wizardview, there is still a couple of fields needed to be filled in the wizard view.
This almost works fine but the only problem is that it validates the form and pop up field error for the fields which are not pre-populated. I tried, if I only redirect to the wizard view without setting the step data, it is fine. It won't validate the form, so no field errors will be displayed.
I am pretty new to Django and not sure if I am doing the right thing and if yes, how can I avoid form to be validated after I set the step data for the current step? Any help will be appreciated.
Implement the WizardView.get_form_initial(step) method in you wizard view class.
This method gets step number as parameters and it should return dict for initial data for the form for that step.
What are some RESTful ways to transition between pages of a multi-page form in Django?
My current method:
form POSTs to same page
form view validates and stores POST data in session
form view redirects to the next form page upon successful validation.
next form checks if previous data exists. if not, redirects to first form.
Are redirects between form pages bad? Should forms POST to the next form page? If so, where should form validation happen?
What you're doing sounds like an implementation of the PRG model for handling multi step forms.
You probably want to POST to the current step, and then redirect to the next step only if the form validates. There is no problem with redirecting between steps; in fact, as you probably discovered, it allows you to support the browser back button in your forms.
Django has form wizards which handle this machinery (in case you were unaware).
http://docs.djangoproject.com/en/dev/ref/contrib/formtools/form-wizard/