Django SessionWizardView jumps back to the first step after page is reloaded - django

I am working with a SessionWizardView which is managing two forms. When I reload the page at the last step for instance I am back at the first step and have to type in all the fields again.
Is this the intended behaviour? If so, is it possible to get back to step I was at before I reloaded the page? Of course all the fields should be filled out accordingly.
class ManufacturingCalculatorWizard(SessionWizardView):
def get_template_names(self):
TEMPLATES = {
"blueprint": "manufacturing/forms/select_blueprint.haml",
"calculator": "manufacturing/forms/calculator.haml"
}
return [TEMPLATES[self.steps.current]]
def done(self, form_list, **kwargs):
form_data = [form.cleaned_data for form in form_list]
rcontext = RequestContext(self.request, { 'data' : calculate_manufacturing_job(form_data) })
return render_to_response('manufacturing/forms/result.haml', rcontext)

Page rendered after done method is not part of wizard, so when you reload it, django will try to redirect to first page as new session of wizard.
If you want to add last step as something like preview and confirmation page, you can add a new step with dummy form and show appropriate data using the template. To get data from previous steps you can make use of get_context_data method of view, to build context with cleaned data of previous forms.

Related

Refresh Django wizard form after browser's back button

I am using SessionWizardView from django-formtools project.
I've noticed that after successfully passing all form checks and executing done() function, which redirects to completely different view, user can still hit browser Back button and re-fill form again.
Isn't there any way to prevent that? I would assume that it would be some kind of session cleaning mechanism. But I cannot find any in documentation.
After some playing around I've found that it can be achieved in two lines:
def done(self, form_list, form_dict, **kwargs):
#regular form processing
self.instance_dict = None
self.storage.reset()
Now, after pressing Back button and submitting form it fails because no data exists and resets to first screen.

Django - How to stay on the same page without refreshing page?

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

Django wizardview: how to set up step data without validating the form

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.

changing CreateView behavior to preview data before save in django

I have gotten Creatview() class based function to work. When the submit succeeds, it has already the data and shows the 'success' page.
I'd like to change this behavior this way: When the CreateView() succeeds, I'd like the data to get validated, but not saved. Instead of going to the success page, I'd like to use the DetailView() class to display the newly created instance, so the user can see how it is going to look like when the data is eventually saved..
Once the user is happy with the data displayed, the user can click "save" in which case the data is saved and the CreateView() is completed or the user can click "re-edit", and go back to the form to change the data and then be shown the newly created instance using DetailView() (and repeat until the user is satisfied). What is the best way to do this using class based views elegantly?
from django.views.generic.edit import CreateView
from restaurant.models import Restaurant
from restaurant.forms import RestaurantForm
import uuid
class RestaurantCreate(CreateView):
form_class = RestaurantForm
template_name = 'restaurant_form.html'
model = Restaurant
def form_valid(self, form):
form.instance.created_by = self.request.user
form.instance.life_id = str(uuid.uuid1())
return super(RestaurantCreate, self).form_valid(form)
Also, I do know about Form wizard, but I do not have multiple page forms. Even if I ignore that, Form wizard's does not give the opportunity to preview data before the final save.
Edit: Related discussion on google groups, but no solutions
Here's what I should do:
Overwrite the form_valid method of the RestaurantCreate class and let the save the form in a session. From there you can redirect to another view , your RestaurentDetail view, there you would overwrite the get_object method by reading out the form out of the session and displaying what you need.
There I would also place a form with all fields hidden, except the submit/save button. The form will be populated by whatever was in your session. So when the user presses save a POST is done to another view RestaurantFinalCreate view for example. There you can just implement the CreateView as normal.
If you're uncertain which method to overwrite and how, take a look at: http://ccbv.co.uk/ it has been really helpful to me.
Also don't use super in the form_valid method of the RestaurantCreate view since that would trigger a save in the parent class ModelFormMixin.

How to extend django admin view?

i want to display additional sidebar in my django admin index. I have created templates/admin/index.html and it show up. Now i need some data from model. To do this I have created index function in the file admin/views.py
def index(request):
var = 'var'
return render_to_response('admin/index.html', {'var': var})
Without this function I have error ViewDoesNotExist.
However template not react for this sample variable 'var'. Moreover my app doesn't display in the index. I have only auth app.
I think that I'm overwriting index function form admin view. How to properly overwrite this function?
Instead of overwriting the view entirely, you can add logic to the views in your ModelAdmin (admin.py) class:
https://docs.djangoproject.com/en/dev/ref/contrib/admin/#other-methods
so for example:
class MyAdmin(admin.ModelAdmin)
...
def add_view(self, request, form_url='', extra_context=None):
# Do some extra queries that will get passed to the template
c = {'x':SomeModel.objects.all()}
super(MyAdmin, self).add_view(request, extra_context=c)
Consider using django admin tools https://bitbucket.org/izi/django-admin-tools/wiki/Home
then you get commands like manage.py customdashboard, manage.py custommenu etc.
It even has a nice bookmark-functionality to quickliy jump to certain objects or list pages.