Reputation: 11553
I'm wondering, in terms of database efficiency, if I edit the return __unicode__
method and do something like this:
class AnyModel(models.Model):
a_field = models.ForeignKey(A)
b_field = models.ForeignKey(B)
def __unicode__(self):
return "A - B: %s - %s " % (self.a_field.a2.a3, self.b_field.b2.b3)
So, the __unicode__
method will hit the foreign key's foreign key's foreign keys, get a string and then return it.
... Is it too expensive? What criteria should I follow? Is there any general advice I could use? Is it better not to write this kind of __unicode__
methods?
Upvotes: 1
Views: 48
Reputation: 2569
This is what happening with this structure:
def __unicode__(self):
return "A - B: %s - %s " % (self.a_field.a2.a3, self.b_field.b2.b3)
Hits :
(0.000) QUERY = 'SELECT "core_a"."id", "core_a"."a2_id" FROM "core_a" WHERE "core_a"."id" = %s' - PARAMS = (2,); args=(2,)
(0.000) QUERY = 'SELECT "core_a2"."id", "core_a2"."a3_id" FROM "core_a2" WHERE "core_a2"."id" = %s' - PARAMS = (1,); args=(1,)
(0.012) QUERY = 'SELECT "core_a3"."id" FROM "core_a3" WHERE "core_a3"."id" = %s' - PARAMS = (1,); args=(1,)
(0.000) QUERY = 'SELECT "core_b"."id", "core_b"."b2_id" FROM "core_b" WHERE "core_b"."id" = %s' - PARAMS = (1,); args=(1,)
(0.000) QUERY = 'SELECT "core_b2"."id", "core_b2"."b3_id" FROM "core_b2" WHERE "core_b2"."id" = %s' - PARAMS = (1,); args=(1,)
(0.005) QUERY = 'SELECT "core_b3"."id" FROM "core_b3" WHERE "core_b3"."id" = %s' - PARAMS = (1,); args=(1,)
But, if you do this,:
def __unicode__(self):
a_relation = AnyModel.objects.select_related('a_field__a2__a3').get(pk=self.pk)
b_relation = AnyModel.objects.select_related('b_field__b2__b3').get(pk=self.pk)
return "A - B: %s - %s " % (a_relation.a_field.a2.a3, b_relation.b_field.b2.b3)
When execute the line :
a_relation = AnyModel.objects.select_related('a_field__a2__a3').get(pk=self.pk)
1 hit :
(0.000) QUERY = 'SELECT "core_anymodel"."id", "core_anymodel"."a_field_id", "core_anymodel"."b_field_id", "core_a"."id", "core_a"."a2_id", "core_a2"."id", "core_a2"."a3_id", "core_a3"."id" FROM "core_anymodel" INNER JOIN "core_a" ON ( "core_anymodel"."a_field_id" = "core_a"."id" ) INNER JOIN "core_a2" ON ( "core_a"."a2_id" = "core_a2"."id" ) INNER JOIN "core_a3" ON ( "core_a2"."a3_id" = "core_a3"."id" ) WHERE "core_anymodel"."id" = %s' - PARAMS = (1,); args=(1,)
and When execute the second line:
b_relation = AnyModel.objects.select_related('b_field__b2__b3').get(pk=self.pk)
+1 Hit:
(0.000) QUERY = 'SELECT "core_anymodel"."id", "core_anymodel"."a_field_id", "core_anymodel"."b_field_id", "core_b"."id", "core_b"."b2_id", "core_b2"."id", "core_b2"."b3_id", "core_b3"."id" FROM "core_anymodel" INNER JOIN "core_b" ON ( "core_anymodel"."b_field_id" = "core_b"."id" ) INNER JOIN "core_b2" ON ( "core_b"."b2_id" = "core_b2"."id" ) INNER JOIN "core_b3" ON ( "core_b2"."b3_id" = "core_b3"."id" ) WHERE "core_anymodel"."id" = %s' - PARAMS = (1,); args=(1,)
And when execute
return "A - B: %s - %s " % (self.a_field.a2.a3, self.b_field.b2.b3)
Doesn't hit the database.
. 1 - Edit
You can join this, to :
def __unicode__(self):
relation = AnyModel.objects.select_related('a_field__a2__a3', 'b_field__b2__b3').get(pk=self.pk)
return "A - B: %s - %s " % (relation.a_field.a2.a3, relation.b_field.b2.b3)
and will hit only once.
(0.000) QUERY = 'SELECT "core_anymodel"."id", "core_anymodel"."a_field_id", "core_anymodel"."b_field_id", "core_a"."id", "core_a"."a2_id", "core_a2"."id", "core_a2"."a3_id", "core_a3"."id", "core_b"."id", "core_b"."b2_id", "core_b2"."id", "core_b2"."b3_id", "core_b3"."id" FROM "core_anymodel" INNER JOIN "core_a" ON ( "core_anymodel"."a_field_id" = "core_a"."id" ) INNER JOIN "core_a2" ON ( "core_a"."a2_id" = "core_a2"."id" ) INNER JOIN "core_a3" ON ( "core_a2"."a3_id" = "core_a3"."id" ) INNER JOIN "core_b" ON ( "core_anymodel"."b_field_id" = "core_b"."id" ) INNER JOIN "core_b2" ON ( "core_b"."b2_id" = "core_b2"."id" ) INNER JOIN "core_b3" ON ( "core_b2"."b3_id" = "core_b3"."id" ) WHERE "core_anymodel"."id" = %s' - PARAMS = (1,); args=(1,)
Upvotes: 2