1

I'm trying to create a confirmation page in Django. I have one view which renders a form, then user clicks on Submit and the objects are saved into the database.

What I want to do is not to save objects into the database when user clicks on submit. I want to render another page, where user can confirm his order so he can see there all objects he will create and click on confirm.

So I've created another view which is called when form is submitted. It should show a table with data and then, if user clicks on Confirm, it should save objects. The problem is - since I'm calling the view and passing there an old request, the request is POST so I can't detect a difference between click on submit and redirect from old view.

So I will probably need to put a parameter 'confirm' to request I'm sending to the next view.

Normally, I would put there if request.method == 'POST' > save objects else render table with values

This is the original view which renders a form an save objects:

def create_order(request):
    import pdb
    pdb.set_trace()
    LanguageLevelFormSet = formset_factory(LanguageLevelForm, extra=5, max_num=5)
    language_level_formset = LanguageLevelFormSet(request.POST or None)
    job_creation_form = JobCreationForm(request.POST or None, request.FILES or None)

    context = {'job_creation_form': job_creation_form,
               'formset': language_level_formset}

    if request.method == 'POST':
        if job_creation_form.is_valid() and language_level_formset.is_valid():
            cleaned_data_job_creation_form = job_creation_form.cleaned_data
            cleaned_data_language_level_formset = language_level_formset.cleaned_data
            for language_level_form in [d for d in cleaned_data_language_level_formset if d]:
                language = language_level_form['language']
                level = language_level_form['level']

                job = Job(
                        customer=request.user,
                        text_to_translate=cleaned_data_job_creation_form['text_to_translate'],
                        file=cleaned_data_job_creation_form['file'],
                        short_description=cleaned_data_job_creation_form['short_description'],
                        notes=cleaned_data_job_creation_form['notes'],
                        language_from=cleaned_data_job_creation_form['language_from'],
                        language_to=language,
                        level=level,
                )
                job.save()            
            return HttpResponseRedirect('/order-success')
        else:
            return render(request, 'auth/jobs/create-job.html', context=context)

    return render(request, 'auth/jobs/create-job.html', context=context)

This is the new approach:

def create_order(request):
    LanguageLevelFormSet = formset_factory(LanguageLevelForm, extra=5, max_num=5)
    language_level_formset = LanguageLevelFormSet(request.POST or None)
    job_creation_form = JobCreationForm(request.POST or None, request.FILES or None)

    context = {'job_creation_form': job_creation_form,
               'formset': language_level_formset}

    if request.method == 'POST':
        if job_creation_form.is_valid() and language_level_formset.is_valid():
            cleaned_data_job_creation_form = job_creation_form.cleaned_data
            cleaned_data_language_level_formset = language_level_formset.cleaned_data

            context = {
                'cleaned_data_job_creation_form':cleaned_data_job_creation_form,
                "cleaned_data_language_level_formset":cleaned_data_language_level_formset,
            }

            return confirm_order(request,context)
        else:
            return render(request, 'auth/jobs/create-job.html', context=context)
    return render(request, 'auth/jobs/create-job.html', context=context)

def confirm_order(request,context):
    cleaned_data_job_creation_form = context['cleaned_data_job_creation_form']
    cleaned_data_language_level_formset = context['cleaned_data_language_level_formset']

    if request.method == 'POST': # HERE IS THE PROBLEM, It's POST in both cases
        for language_level_form in [d for d in cleaned_data_language_level_formset if d]:
            language = language_level_form['language']
            level = language_level_form['level']

            Job.objects.create(
                    customer=request.user,
                    text_to_translate=cleaned_data_job_creation_form['text_to_translate'],
                    file=cleaned_data_job_creation_form['file'],
                    short_description=cleaned_data_job_creation_form['short_description'],
                    notes=cleaned_data_job_creation_form['notes'],
                    language_from=cleaned_data_job_creation_form['language_from'],
                    language_to=language,
                    level=level,
            )
        return HttpResponseRedirect('/order-success')
    file = cleaned_data_job_creation_form['file']
    try:
        count =  utilities.docx_get_characters_number(file)
    except utilities.UnknownCharactersNumberException:
        count = 0

    jobs = []
    for language_level_form in [d for d in cleaned_data_language_level_formset if d]:
        language = language_level_form['language']
        level = language_level_form['level']
        d={}
        d['language_from']=cleaned_data_job_creation_form['language_from'].name
        d['language_to']=language
        d['number_of_characters']=count
        d['price_per_sign']=LanguageLevel.objects.get(language=language,level=level).price_multiplier*AdminContact.objects.all()[0].price_per_sign
        d['estimated_price']=count*d['price_per_sign']
        jobs.append(d)

    table = CreatedOrdersTable(jobs)
    context = {'table':table}
    return render(request, 'auth/jobs/confirm-order.html', context=context)
Milano
  • 18,048
  • 37
  • 153
  • 353
  • And what is your question? – Daniel Roseman Jun 06 '16 at 08:04
  • The main problem is that when I call confirm_order from the create_order view, It creates objects automatically, I want confirm_order to render a confirm-order.html first, and after click on Confirm, it would save objects. So the problem is that row if request.method == 'POST' is called both times - when the view is called from create_order view and when confirm is clicked. – Milano Jun 06 '16 at 08:10
  • I think you should change "return confirm_order(request,context)" to return HttpResponseRedirect(reverse('name_of_your_confirm_view')) – Thinh Phan Jun 06 '16 at 09:21
  • @ThinhPhan But I have to send context to the confirm_order. – Milano Jun 06 '16 at 13:36

2 Answers2

0

There are two ways to do this:

(1) Use a "staging" table / model to store the pending-job-order state without taking any real actions to action the order. This gives the user ability to come back to their session or for you to send reminder to the user later about a job-order in progress, etc. If you choose to do it this way, follow standard guidelines to save to the staging model object and return redirect to the view which will present the confirmation page with the output from this staging table. Once the final order is submitted you can update the actual table and delete the staging table entry.

(2) If you do not want to use the above method consider using a multi-step form functionality to use the session backend to store interim state and forward it to the next page until final submit. If you do not want to do this by hand, check out django-formtools

Bobby Chowdhury
  • 334
  • 1
  • 7
0

Two possible options I would suggest would be

Community
  • 1
  • 1
Garima Singh
  • 233
  • 1
  • 7