return python function variable

Asked

Viewed 739 times

2

I have a function that returns several values, and I wanted to pass two of them out of the function, but when I try it returns that the variable outside the function has not been declared.

To illustrate in the code below, I would like the lists teste3 and teste4 of the function gerar_gráfico, to be used in the function index outside of the function gerar_graficos, remembering that it is a views of Django.

Function code:

class StorageData:
    list_shared = [] #lista compartilhada
    def __init__(self, *dados):
         self.list_shared.extend(dados) #inclui dados na lista

    def extend(self, *args):
         self.list_shared.extend(args)

    def reset(self):
        self.list_shared = [] #reseta lista caso queira zerar ela


def gerar_graficos(request):
    descricao = '01/02/2019 08:00'
    descricao2 = '01/02/2019 09:00'

    if request.method=='POST':
        descricao = request.POST['descricao']
        descricao2 = request.POST['descricao2']
    conn = cx_Oracle.connect('banco')
    cur = conn.cursor()

    cur.execute(consulta do banco)
    teste = []
    teste2 = []
    teste3 = []
    teste4 = []


    d = 0
    for line in cur:
        teste.extend(line)
    for indice, c in enumerate(teste):
        #if c + 0 == c:
            teste3.extend([c - 10000])
        #else:
            d = 0


    cur.execute(consulta do banco)
    for coluna in cur:
        teste2.extend(coluna)
    for indice2, c in enumerate(teste2):
        if indice2 >= d:
            teste4.extend([c])

    transfer = StorageData()
    transfer.reset()
    transfer.extend(teste3,teste4)

    width_n = 0.001
    bar_color = 'yellow'

    cur.close()
    conn.close()

    context = { 'descricao': descricao, 'descricao2': descricao2 }
    return render(request, 'core/graficos_list.html', context)

Code outside the function:

def index(request):
   trans = StorageData()
   my_list = trans.list_shared[0]
   my_list2 = trans.list_shared[1]
   fig = Figure()
   ax = fig.add_subplot(1,1,1)
   ax.plot(my_list, my_list2)
   #ax.bar(x_axis, y_axis, width=width_n, color=bar_color, align='center')
   ax.grid()
   buf = io.BytesIO()
   canvas = FigureCanvas(fig)
   canvas.print_png(buf)
   response=HttpResponse(buf.getvalue(), content_type='image/png')
   return (response)

2 answers

3


It is not possible to access this way because descricao and descricao2 are valid variables only for the scope of the function gerar_graficos().

One solution would be to call these functions calcular_medida() and calcular_data() within the gerar_graficos() that if the x_axis and the y_axis are used in the template.

def gerar_graficos(request):
    descricao = '01/02/2019 08:00'
    descricao2 = '01/02/2019 09:00'

    if request.method=='POST':
        descricao = request.POST['descricao']
        descricao2 = request.POST['descricao2']


    y_axis = calcular_medida(descricao,descricao2)
    x_axis = calcular_data(descricao, descricao2)
    context = { 'descricao': descricao, 'descricao2': descricao2, 'x_axis' : x_axis, 'y_axis': y_axis }
    return render(request, 'core/graficos_list.html', context)

Another method would be to call a function in gerar_gráficos() to do what you want to do.

def gerar_graficos(request):
    descricao = '01/02/2019 08:00'
    descricao2 = '01/02/2019 09:00'

    if request.method=='POST':
        descricao = request.POST['descricao']
        descricao2 = request.POST['descricao2']


    calculaXY(descricao,descricao2)
    context = { 'descricao': descricao, 'descricao2': descricao2 }
    return render(request, 'core/graficos_list.html', context)

def calculaXY(descricao,descricao2):
    y_axis =  []
    x_axis = []
    y_axis = calcular_medida(gerar_graficos.descricao,gerar_graficos.descricao2)
    x_axis = calcular_data(gerar_graficos.descricao, gerar_graficos.descricao2)

I recommend giving a read on Class Based Views that can facilitate this whole question of attributes and functions.

  • the two solutions work well for my question, so I will accept your answer, but what I need is not in question, unfortunately not right, thanks for the help, and if I can help more, I need to have two lists read by two different views

  • @Guilherme Use the View being a class, you can have a class attribute that would be the two lists, and you can use them independently in the two functions.

  • Ai can have two functions in the class that generate two different templates?

  • @William so you get the two lists to be class attributes and shared between the two functions, but if the graph has any relation to the data what you can do is use a front end to generate the Graphics, putting these functions that calculate the measure in the javascript template, so it is easier depending on the application.

  • the graph is generated from the data of the lists, but I will try to make a class with the two functions, being read each by a template, if it doesn’t work, I go to your tip of the front end, thanks brother

2

@William, Dude from what I read in the comments, you need to get two different views to access the same data. You can try to store them in Ssion, such as:

 request.session['descricoes'] = [descrição, descricao2]

But this way I’m not 100% sure it will work, but it doesn’t cost to try. Now you can create a class to do this operation of storing shared data.

class StorageData:
    list_shared = [] #lista compartilhada
    def __init__(self, *dados):
         self.list_shared.extend(dados) #inclui dados na lista

    def reset(self):
        self.list_shared = [] #reseta lista caso queira zerar ela

Ready now to use it, just instantiate the class is pass your lists inside the constructor of it

StorageData (descrição, descricao2)

And when you want to use this data in another view just instantiate the class again without parameters and access the list_shared property.

#outra view para acessar os dados da descricao e descricao2
def sua_view(request):
    storage = StorageData()
    my_list = storage.list_shared # Aqui a propriedade irá retornar os mesmos dados que foi executado por outra instância passando os dados pelo construtor.

Try to make these ways and if it doesn’t work post there to see if there are other forms too.

Using: Here are two different views that will use the class

def transfer(request):

    transfer = Storage()
    transfer.reset() # Coloquei apenas para resetar a lista para cadastrar novamente os mesmos dados, para não ficar adicionando um monte de vez a cada requisição

    descricao = ["Esta lista é a decricao"]
    descricao2 = ["Esta lista é a decricao2"]
    transfer.extend(descricao,descricao2) # Aqui adiciona os dados na classe

    return render(request,'core/transfer.html',context{'descricao':descricao,'descricao2':descricao2})

def Transfer_get(request):
    trans = Storage()
    descricao = trans.list_shared[0]  # Aqui recupera os valores adicionados na classe
    descricao2 = trans.list_shared[1]

    return render(request, 'core/transfer2.html', context={'descricao':descricao,'descricao2':descricao2})

In the template I just showed the data

{{ descricao }}
{{ descricao2 }}

If you prefer you can pass the full list to the templates and it make the interaction in the list and display its data.

def Transfer_get(request):
    trans = Storage()
    lista = trans.list_shared  # Aqui recupera os valores adicionados na classe

    return render(request, 'core/transfer2.html', context={'lista':lista})

And in the template interact this list.

I also created the routes for these views. I made a simple change to the class by adding the extend method().

class Storage:

    list_shared = []

    def __init__(self, *args):
        self.list_shared.extend(args)

    def extend(self, *args):
        self.list_shared.extend(args)

    def reset(self):
        self.list_shared.clear()

Well tested here is the values pass normally to the two views, and if I add any more value in list_shared when you go to the list the new values also appear without problem. If you have done it right and see that there is no mistake and it still doesn’t work, post the code here the way you stayed to see if we can make some change or something.

  • I edited the code of the question and made the changes that Voce gave me, no more error, but generates a chart with no data, I do not know the pq, if I can help, but your solution ta me giving a light at the end of the tunnel

  • edited the response of a look there and see if its implementation looked like this.

  • implementation ta identica, but now it presents the following error: "list index out of range" and this error: "my_list = trans.list_shared[0] "

  • Put your view code where you are creating the list and accessing it, and also the transfer class. Because it will get hard to forget where this error is. This error generated is because you are trying to access an entry from a list that does not exist.

  • I edited the question there with the updated code

  • I did several tests, including two lists I created with values from 0 to 5, and always gives the same error

  • Good guy seems to be all right and it was not to appear this access error to the list at position 0. Try to debug the code to see what is being passed to list_shared, so you can better see the possible errors.

  • now only Monday, code got on the company PC, I’ll try and get back to you

  • Beauty second agent tries to find this mistake. Said good FDS

  • Thanks brother, so nothing in debug returns no errors

  • In your view, when you debug the shared list_shared gets populated? Because if the list_shared is not being filled in the view will give access error even, try to see if what you are passing to list_shared is the way you really imagine. Because now it is more difficult to find the error. Most likely it is time to fill the list in the view. Take a look and do a detailed debug and is as expected.

  • Returns list_shared as empty, I need to see pq

  • there’s some light there?

  • Eae Guilherme, then, man, it’s hard to know why you’re not filling out your list, probably something in your saw’s log. And it gets hard to tell without debugging the code. What I can try is to take know code and do a test here, more precise of a model of results that your query returns, and what the final result expected to send to the other views.

Show 9 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.