Search code examples
pythoncherrypyjinja2

For loop is 'printed' every time I hit refresh


I build simple webpage using CherryPy and Jinja2

The webserver python file:

import cherrypy
from jinja2 import Environment, FileSystemLoader
from soltyslib import listFiles
env = Environment(loader=FileSystemLoader('templates'))
class HelloWorld(object):   
    @cherrypy.expose        
    def index(self):        
        template = env.get_template('index.html')
        result = template.render(name='Pawel',files=listFiles('templates'))
        return result    

cherrypy.quickstart(HelloWorld())

Template file:

Hello {{name}}!
<ul>
{% for file in files %}
    <li>{{file}}</li>
{% endfor %}
</ul>

Ok, and then I run webserver, I go to 127.0.0.1:8080 and see result that is expected:

Hello Pawel!

  • templates\index.html
  • templates\list.html

But then I hit refresh in browser and this is a result:

Hello Pawel!

  • templates\index.html
  • templates\list.html
  • templates\index.html
  • templates\list.html

Why? for loop is evaluated again? How to prevent from doing so?

And in case somebody wondering how listFiles function looks:

import os,sys
from collections import deque
def listFiles(cdir, fileslist=[]):
    basedir = cdir
    queuedir = deque()
    queuedir.append(basedir)
    while len(queuedir) > 0:
        currentbase = queuedir.popleft()
        for f in os.listdir(currentbase):
            f = os.path.join(currentbase,f)
            if os.path.isdir(f):           
                queuedir.append(f)
            else:
                fileslist.append(f)

    return fileslist

Solution

  • Your problem is

     def listFiles(cdir, fileslist=[]):
    

    You're reusing the same list on every call, because default arguments are evaluated only when the function is defined, not every time it's called. See "Least Astonishment" and the Mutable Default Argument for a long discussion if this behavior.

    Do

     def listFiles(cdir, fileslist=None):
         if fileslist is None:
             fileslist = []