Do model attributes in instance methods cause database hits?

Hi, I have been looking for answers on this question but haven’t had much luck. If I have a situation like the following:

class C(models.Model):
    # ...
    pass

class B(models.Model):
    # ...
    c = models.ForeignKey(C)

class A(models.Model):
    # ...
    b = models.ForeignKey(B)

    def save(self,*args, **kwargs):
        do_stuff(self.b)  # Does this do a database lookup?
        do_other_stuff(self.b.c)  # Does this do a database lookup?
        super().save(*args, **kwargs)

Would accessing the model attributes within the save() method like this do extra database queries? The main scenario I am wondering about is if I was creating a new record of ‘A’ through a POST request and I provided instance ‘b’ for initialization, would it hit the database in the save() method to retrieve attribute ‘b’, and nested attribute ‘c’?

What about this?:

a = A.objects.all().first()
a.save()

Would this cause extra db queries within the save() method?

This is going to depend upon what has happened up to this point - how you got to the save method.

In the example you’ve provided where you say that you provided instance b for initialization, Django shouldn’t be retrieving it again within do_stuff. Whether or not the reference to b.c does a lookup is likely to depend upon how you retrieved b - for example, did it include the select_related clause? - or whether or not you’re accessing any attribute of c beyond the id.

For your specific case, you could run runserver_plus (from the always-amazing django-extensions package) with the --print-sql parameter to see all the queries being generated. You could also see this through the just-as-useful django-debug-toolbar.

Ken