Alejandro Veintimilla
Alejandro Veintimilla

Reputation: 11523

Django not updating object in classmethod. Very strange

I don't understand this. This model has a classmethod that looks for all addresses and updates them, but it is not working:

views.py

address = Address.objects.get(id=address_id)
default = request.data.get("default", address.default)
if default.lower() == "true":        
    print "default is true"
    Address.set_default_address(address.id, address.client)
else:
    print "default is false"
    address.default = default

print "in view -> address.id - address.default: %s - %s" % (address.id, address.default)

Address.set_default_address:

class Address(models.Model):
    ...
    default = models.BooleanField(default=False)

    @classmethod
    def set_default_address(cls, address_id, client):
        client_addresses = Address.objects.filter(client=client)
        print "client_addresses: %s" % client_addresses
        for address in client_addresses:
            if address.id != address_id:
                print "address is set to False - address id: %s" % address.id
                address.default = False
                address.save()
            else:
                print "address is set to True! - address id: %s" % address.id
                address.default = True
                address.save()
                print "classmethod address.id - address.default: %s - %s" % (address.id, address.default)

The classmethod is designed to be called if the new address has to be set to default=True and change all other addresses to default=False.

The printed output looks like this:

default is true

client_addresses: [,]

address is set to False - address id: 1

address is set to True! - address id: 2

classmethod address.id - address.default: 2 - True

in view -> address.id - address.default: 2 - False

As you can see, the print called in the classmethod looks like it set the address.default to True, but the print in the view shows the opposite. Why?

Upvotes: 0

Views: 327

Answers (1)

Alasdair
Alasdair

Reputation: 308889

When you save the address in the class method, it updates the object in the database, but not in the view.

You can call the refresh_from_db method to reload the values from the database.

if default.lower() == "true":        
    print "default is true"
    Address.set_default_address(address.id, address.client)  # updates the object in the db
    print address.default # will print False
    address.refresh_from_db()
    print address.default # will print True

See the docs on refreshing objects from the database for more details.

Upvotes: 1

Related Questions