You are not logged in.

#1 2009-10-25 12:54:00

FeatherMonkey
Member
Registered: 2007-02-26
Posts: 313

[Solved]Wrong results from a while loop, django why?

Using django querysets I get a result returned, I'm unpacking it to repack to add a new key=value, the unpacking works but in placing it in a list of dictionaries I end up with the second instance twice. I just don't understand why...

newdict = {}
get_rec = []
rec_id = objects.filter(search__icontains=value).values('key') # Query to count return >1 int
n = len(rec_id)-1 # initialise counter for while loop
while n >= 0:
    # return single object
    ser = objects.filter(id=rec_id).values()
    for i in ser:
        for more in i:
            newdict[more] =  i[more] # Rebuild a dict to add a new key=value
        newdict['drag'] = "this_word"
    get_rec.append(newdict) # On first loop over its correct on second I have two versions of the second newdict
    n = n - 1

I'm sure this a real newbies question but I just don't understand or can see why it happens. I've even printed the get_rec and on the first instance it appends the newdict fine, but on the second loop over it seems to re-initialise the get_rec and adds 2 copies of the 2nd instance of newdict.

Perhaps someone knows of a better way of doing this.

Last edited by FeatherMonkey (2009-10-26 15:08:30)

Offline

#2 2009-10-26 14:36:50

FeatherMonkey
Member
Registered: 2007-02-26
Posts: 313

Re: [Solved]Wrong results from a while loop, django why?

Am I missing something really basic? on further prodding I realised I had an unneeded for so..

newdict = {}
get_rec = []
rec_id = Model.objects.filter(field__icontains="value").values('id_field')
n = len(rec_id)-1
while n >= 0:
    ser = Related_Model.objects.filter(id=rec_id[n][id_field']).values()
    for i in ser[0]:
        newdict[i] = ser[0][i]
    newdict['custom_field'] = "value"
    get_rec.append(newdict)
    n = n - 1

The more I look at the while for loop the less I understand why it is happening. Testing without the while loop appending a dictionary to a list of dictionaries does as expected.

Simplifying and adding a print get_rec after the append without the custom field returns this ...

[{'link_id': 1, 'field': u'value', 'field': u'', 'field': u'', 'field': u'', 'field': u'value', 'id': 10}] # first append

[{'link_id': 2, 'field': u'value', 'field': u'', 'field': u'', 'field': u'', 'field': u'value', 'id': 9},{'link_id': 2, 'field': u'value', 'field': u'', 'field': u'', 'field': u'', 'field': u'value', 'id': 9}]

Can anyone give me a hint as to the why?

Offline

#3 2009-10-26 14:48:57

pointone
Wiki Admin
From: Waterloo, ON
Registered: 2008-02-21
Posts: 379

Re: [Solved]Wrong results from a while loop, django why?

newdict always refers to the same dictionary; call-by-reference and all that fun.

So, through the first loop, you update newdict and append it to the list. Then, you update newdict (which alters the dictionary already appended) and append a second reference.

Try:

get_rec = []
rec_id = Model.objects.filter(field__icontains="value").values('id_field')
n = len(rec_id)-1
while n >= 0:
    newdict = {} # create a new dictionary for each iteration
    ser = Related_Model.objects.filter(id=rec_id[n][id_field']).values()
    for i in ser[0]:
        newdict[i] = ser[0][i]
    newdict['custom_field'] = "value"
    get_rec.append(newdict)
    n = n - 1

Or...

newdict = {}
get_rec = []
rec_id = Model.objects.filter(field__icontains="value").values('id_field')
n = len(rec_id)-1
while n >= 0:
    ser = Related_Model.objects.filter(id=rec_id[n][id_field']).values()
    for i in ser[0]:
        newdict[i] = ser[0][i]
    newdict['custom_field'] = "value"
    get_rec.append(newdict.copy()) # append a copy of the dictionary, rather than the 'global' reference
    n = n - 1

Last edited by pointone (2009-10-26 14:50:03)


M*cr*s*ft: Who needs quality when you have marketing?

Offline

#4 2009-10-26 15:07:51

FeatherMonkey
Member
Registered: 2007-02-26
Posts: 313

Re: [Solved]Wrong results from a while loop, django why?

Thank you that was exactly the problem your first solution solved it fine.

So it seems it was a rather basic problem it was only when you put it into words it made sense, now I can clearly see it, though I'm aware of call-by-reference I clearly wasn't too aware of the implications. As they say the only stupid questions are the ones not asked.

Thank you for the moment of clarity, think that little understanding has been one more step on getting my head around object programming. Now to mark this as solved.

Offline

Board footer

Powered by FluxBB