0

Hard to explain this in a simple subject. This is with a GET, no POSTs.

I have a function defined in a different file, we'll say list_gen.py that returns list 'gen_list'. 'gen_list' is a global variable here.

In the views.py, I call this function and assign the output as 'output_list' and send it with the return as such: " return render(request, 'detail.html', {'output_list':output_list}.

Then, in detail.html I simply place the results with {{output_list}}.

When I visit the page, I see the exact output I expected. But, if press refresh, the output duplicates and continues to do so each time I press refresh or if I visit another entry that uses that detail.html page.

Has anyone seen this before?

Below is the view in question. The suspect list is "ped"

@login_required(login_url='/accessdenied/')
def detail(request, did):
    try:
        dog = Dogs.objects.get(did__exact=did)
        
        resp = pedigree(did, 3)
        ped = ''.join(map(str, resp))
        
        try:
            dam = Dogs.objects.get(did__exact=dog.dam).registered_name
        except:
            dam = "Not Listed"
        try:
            sire = Dogs.objects.get(did__exact=dog.sire).registered_name
        except:
            sire = "Not Listed"
        parents = {'dam': dam, 'sire': sire}

    except Dogs.DoesNotExist:
        raise Http404("Dog does not exist") 
    
    return render(request, 'main/detail.html', {'dog': dog, 'parents': parents, 'ped': ped})

Below am image of the first time visiting the details for a specific entry (a dog): enter image description here

And refresh a few times, and then visit a different entry. Note that each recent entry appears at the bottom. enter image description here

The pedigree function (which calls printTree). Yes... I am making an html file into a list which is probably dumb. BUT, I get the exact same duplication if I use the "dog" list you see commented out where used.

dog = []
ped = ['<table border=1>']
def pedigree(did, max):
    '''
    :param did: id of the child dog
    :param max: max number of generations to display
    :return: list of dogs
    '''
    con = sqlite3.connect(f)
    con.row_factory
    cursor = con.execute('SELECT "Registered Name", ROUND(((JulianDay("now") - JulianDay("Date of Birth"))/365.25),1), "Sex" FROM dogs where did IS %s ' % did).fetchall()
    for row in cursor:
        name, age, gender = row[0], row[1], row[2]
    sql = "SELECT a.Sire, a.Dam, s.'Registered Name', d.'Registered Name' FROM dogs a INNER JOIN dogs s ON a.Sire = s.did INNER JOIN dogs d ON a.Dam = d.did WHERE a.did = "
    printTree(sql, did, name, 0, max)
    return ped
    #return dog


def printTree(stmt, did, name, N, max):
    '''
    :param stmt: sql statement to query information
    :param did: dog to obtain information on
    '''
    rspan = 2**(max-N)

    if (rspan > 1):
        ped.append('<td rowspan='+str(rspan)+'><a href=/dogs/'+str(did)+'>'+name+'</td>')
        # dog.append({'name': name, 'rspan': rspan})
    else:
        ped.append('<td><a href=/dogs/'+str(did)+'>'+name+"</td>")

    if (N == max):
        ped.append("</tr><tr>")

    if(N < max):
        s = None
        d = None
        sn = None
        dn = None
        con = sqlite3.connect(f).execute(stmt+str(did)).fetchall()
        for row in con:
            s, d, sn, dn = row[0], row[1], row[2], row[3]
        if (s and sn) != None:
            printTree(stmt, s, sn, N+1, max)
        if (d and dn) != None:
            printTree(stmt, d, dn, N+1, max)

JohnD
  • 61
  • 6
  • Can you share your view? Sounds like maybe `output_list` is a global variable or class attribute that you are just appending to – Iain Shelvington Jun 23 '20 at 00:47
  • @IainShelvington Certainly. Added the view and some images. – JohnD Jun 23 '20 at 00:56
  • Can you share the `pedigree` function too, it seems like that is where the problem is – Iain Shelvington Jun 23 '20 at 00:58
  • 1
    Without seeing your code we can only speculate, but my money is on a mutable default argument. See https://stackoverflow.com/questions/1132941/least-astonishment-and-the-mutable-default-argument – Selcuk Jun 23 '20 at 00:58
  • Added the whole scope here now. @Selcuk That does seem close to my issue maybe. But the repeat only occurs in the viewed html on the server. Console output of "ped" at the same time does not show these duplicates. – JohnD Jun 23 '20 at 01:04
  • 2
    `ped` is a global list that you constantly append to in the function `printTree` but never empty. Of course it's going to grow and grow. – Iain Shelvington Jun 23 '20 at 01:11
  • Thanks! That led me to figuring out why my previous attempts to clear the list didn't work... I may have been editing the wrong file... I am good to go now with this: ped = [] ped.clear() ped.append('') thanks all, lessons learned
    – JohnD Jun 23 '20 at 02:10

1 Answers1

0

Thanks to the comments, I fixed by altering the pedigree function as such to clear the list.

ped = []
def pedigree(did, max):
    '''
    :param did: id of the child dog
    :param max: max number of generations to display
    :return: list of dogs
    '''
    ped.clear()
    ped.append('<table border=1>')
    con = sqlite3.connect(f)
JohnD
  • 61
  • 6