1

I'm asking How I can call a variable with Python 2.7 and Django 1.10 which is defined in the function1 into the function2.

I defined a function1 like that :

def Test(request) :
  form = TestForm(request.POST or None)
  if form.is_valid() :  
      instance = form.save(commit=False)
      return HttpResponseRedirect('toto')
  context = {
      "form" : form,
      }
  return render(request, 'form_Test.html', context)

And I would like to call the variable instance inside my function2 :

def Test2(request) :
    
    identity = instance.lastname

    context = {
       "identity" : identity,
   }

    return render(request, 'test2_identity.html',context)

I would like to know How it's possible to do this handle ?

----------------------------------------------------------------------------------------------

EDIT :

I tried to handle all things in the same view, with a preview step :

#views.py

def IdentityFormulary(request) :

    form = IdentityForm(request.POST or None)
    template_name = 'form_Identity.html'

    if form.is_valid() :  
        if '_preview' in request.POST :
            post = form.save(commit=False)
            template_name = 'preview.html'
            #if .is_valid() :
                #post=form.save()
        
        elif '_save' in request.POST :
            post = form.save()
            return HttpResponseRedirect('formulaire_traite')

    context = {
        "form" : form,
            }

    return render(request, template_name, context)


def CompletedFormulary(request) :
    
    identity = Identity.objects.all().order_by("-id")[0]

    context = {
       "identity" : identity,
   }

    return render(request, 'recapitulatif_identity.html',context)

The preview.html file :

<!--preview.html-->

<h2 align="center"> Prévisualisation du formulaire </align> </h2>

{% block content %} 

<h3> Récapitulatif des données enregistrées : </h3>

<li> Civilité : {{form.title}}</li>
<li> Nom : {{form.lastname}}</li>
<li> Prénom : {{form.firstname}}</li>
<li> Sexe : {{form.sex}}</li>
<li> Date de Naissance : {{form.birthday}}</li>
<li> Ville de Naissance : {{form.birthcity}}</li>
<li> Pays de Naissance : {{form.birthcountry}}</li>
<li> Nationalité : {{form.nationality}}</li>
<li> Profession : {{form.job}}</li>
<li> Adresse : {{form.adress}}</li>
<li> Ville : {{form.city}}</li>
<li> Code Postal : {{form.zip}}</li>
<li> Pays : {{form.country}}</li>
<li> Email : {{form.mail}}</li>
<li> Téléphone : {{form.phone}}</li>

{% endblock %} 

<br></br>

<input type ="submit" name="_save" value="Valider la fiche individuelle" />

I 'm just blocking with the submit button in my preview.html because for the moment, it doesn't work

Community
  • 1
  • 1
  • http://stackoverflow.com/questions/423379/using-global-variables-in-a-function-other-than-the-one-that-created-them – Risul Islam Nov 25 '16 at 15:22
  • Is your Test2 view the one that is redirected to with HttpResponseRedirect('toto')? – RemcoGerlich Nov 25 '16 at 15:23
  • @RisulIslam I got an error because my global variable is not an int, or string but it's an object –  Nov 25 '16 at 15:24
  • If so, then it is completely independent of the previous view, if it wants to do something with instance, it should have something in its url to find instance (like its primary key) and then retrieve it from the database using that. – RemcoGerlich Nov 25 '16 at 15:24
  • @RemcoGerlich Yep it's exactly that. –  Nov 25 '16 at 15:25
  • @I don't want to search from database because I want to get a data resume (something like cache) before to validate it. In this way, I can control data form before submission and obviously write data inside the database. I don't know if it's really clear –  Nov 25 '16 at 15:28
  • When you call form.save, it's saved to the database. Then you go back to the browser (with the redirect) and the current request ends. Django forgets all that happened before. Then the browser decides to follow the redirect, and it enters your Test2 view as a brand new request completely unrelated to what happened before. The only way to get back at what happened before is to store it somewhere (like, in a database). – RemcoGerlich Nov 25 '16 at 15:46
  • 1
    If you want to validate the form before saving it, put it in validation methods in the form class; it'll happen in Test1 and Test2 will have nothing to do with the validation. – RemcoGerlich Nov 25 '16 at 15:47
  • 1
    You wouldn't be able to get instance as the variables in your view function exists for `request -> response` cycle. You can cache this submitted form in Redis. – Oluwafemi Sule Nov 25 '16 at 15:47
  • @OluwafemiSule caching in redis is just storing data in a database - a different kind of database but still a database. If the OP problem is to validate the form, then the sensible thing to do is to do it in the form itself... – bruno desthuilliers Nov 25 '16 at 16:03
  • Sure @brunodesthuilliers, that's the way to go about it. However, it seems what he want to do is access the submitted form in a view function inside another view function. – Oluwafemi Sule Nov 25 '16 at 17:10
  • @OluwafemiSule yes obviously, but the point is: WHY does the OP _thinks_ he wants this ? – bruno desthuilliers Nov 28 '16 at 09:51

2 Answers2

2

Short answer: what your asking for is not possible, period. Even a global variable wouldn't work, since nothing garantees that both requests will be served by the same process (and even then there would be a lot of other unsolvable issues).

FWIW that's actually one of the reasons why we use databases a lot in web development - so we can persist state between requests (where a single-user Desktop app could just keep state in memory for the session).

Now you mention in your comments that

I don't want to search from database because I want to get a data resume (something like cache) before to validate it. In this way, I can control data form before submission

If that's the reason you want to share instance between two views then it's just not the way - you have a form, forms DO have validation (that's actually the main reason for django.forms - validating user-submitted data), and you can hook into the validation process at different point to perform any extra validation. IOW : there's just not reason to try to share a variable between two views to validate a form.

EDIT: ok now we have the X part of the XY problem:

What I would like to get is : user are filling a form in a HTML page. Then, he gets a resume and 2 options : submit (with data saving in MySQL database) or modify data form. The second option lets to get one more time the filled form and he can modify one or several values, then submit to database

And the answer is : you don't need two views to handle the case, you just have to track the current "step" (initial submission / preview / edit / final submission), which is not really rocket science - this is easily done with the request method (a GET is for an empty form, anything else is either asking for a preview, edit or final submission) and the submit buttons names (to find out which of the preview / edit / final submission action should be performed). You can get an unsaved instance (for preview) using form.save(commit=False).

bruno desthuilliers
  • 75,974
  • 6
  • 88
  • 118
  • Thank you to answered me. What I would like to get is : user are filling a form in a HTML page. Then, he gets a resume and 2 options : submit (with data saving in MySQL database) or modify data form. The second option lets to get one more time the filled form and he can modify one or several values, then submit to database –  Nov 26 '16 at 14:31
  • Then you should handle all this in the same view, using a hidden field to store the current step. – bruno desthuilliers Nov 28 '16 at 09:50
  • I was trying to handle all processes in the same view as you said. I also used `commit=False` in order to get data unsaved. Your track is what I want to get (initial submission / preview / edit/ final submission). I'm working on but for the moment, I don't get some result. It's the first time (2 weeks period) I'm using Django, so some steps are still black magic ^^ –  Nov 28 '16 at 10:16
  • I edited my post with my progress. I'm just blocking on submission in preview.html template –  Nov 28 '16 at 10:42
  • The submit button has to be a in `
    ` tag to do anything. And you'd probablu have less work with a single template and passing a flag in the context to tell if you have to display the preview. Also, you should always explicitely test against `request.method`, relying on `request.POST` being empty can create subtle problems (been here, done that...).
    – bruno desthuilliers Nov 28 '16 at 10:55
  • It works. I forgot some things and now I don't get errors. Thank you very much ! –  Nov 28 '16 at 10:58
0

This is How I resolved my problem thanks to @brunodesthuilliers :

My views.py file :

#-*- coding: utf-8 -*-

from django.shortcuts import render, render_to_response
from django.http import HttpResponseRedirect, HttpResponse
from django.template import loader
from .models import Identity, Country
from .forms import IdentityForm


def IdentityAccueil(request) :

    template = loader.get_template('accueil_Identity.html') 
    return HttpResponse(template.render(request))

def IdentityFormulary(request) :

    form = IdentityForm(request.POST or None)
    template_name = 'form_Identity.html'

    if form.is_valid() :  
        if '_preview' in request.POST :
            post = form.save(commit=False)
            template_name = 'preview.html'

        elif '_save' in request.POST :
            post = form.save()
            return HttpResponseRedirect('formulaire_traite')

    context = {
        "form" : form,
            }

    return render(request, template_name, context)


def CompletedFormulary(request) :

    identity = Identity.objects.all().order_by("-id")[0]

    context = {
       "identity" : identity,
   }

    return render(request, 'recapitulatif_identity.html',context)

My preview.html file :

<h2 align="center"> Prévisualisation du formulaire </align> </h2>

<form method='POST' action=''> {% csrf_token %}
{% block content %} 

<h3> Récapitulatif des données enregistrées : </h3>

<li> Civilité : {{form.title}}</li>
<li> Nom : {{form.lastname}}</li>
<li> Prénom : {{form.firstname}}</li>
<li> Sexe : {{form.sex}}</li>
<li> Date de Naissance : {{form.birthday}}</li>
<li> Ville de Naissance : {{form.birthcity}}</li>
<li> Pays de Naissance : {{form.birthcountry}}</li>
<li> Nationalité : {{form.nationality}}</li>
<li> Profession : {{form.job}}</li>
<li> Adresse : {{form.adress}}</li>
<li> Ville : {{form.city}}</li>
<li> Code Postal : {{form.zip}}</li>
<li> Pays : {{form.country}}</li>
<li> Email : {{form.mail}}</li>
<li> Téléphone : {{form.phone}}</li>

{% endblock %} 

<br></br>

<input type ="submit" name="_save" value="Valider la fiche individuelle" />

</form>