Jin. K
Jin. K

Reputation: 141

django query optimization in iteration

class Value(models.Model):
    attribute = models.ForeignKey(Attribute)
    platform = models.ForeignKey(Platform)
    value = models.CharField(max_length=30)

class Attribute(models.Model):
    name = models.CharField(max_length=50)
    ....

1.

for attribute in attributes:
    attribute.value = Value.objects.get(Q(attribute__id=attribute.id) & Q(platform__id=platform.id))

2.

values = Value.objects.filter(platform__id=platform.id)

for attribute in attributes:
    attribute.value = values.get(attribute__id=attribute.id)

Can I say the method 2 is more efficient than 1 because it prevents excessive DB query?

Upvotes: 0

Views: 79

Answers (2)

Iain Shelvington
Iain Shelvington

Reputation: 32244

Example 2 can be reduced to only 1 DB query like so:

values = Value.objects.filter(platform__id=platform.id)
attribute_values = {value.attribute_id: value for value in values}

for attribute in attributes:
    attribute.value = attribute_values[attribute.id]

I'm assuming that Value.attribute is a ForeignKey

Upvotes: 2

Shang Wang
Shang Wang

Reputation: 25539

I wouldn't say that's the case, because filter and get are just building up some where statements for sql query. You might think that django is caching the value values because you only do it once, but the query is not even evaluated when you do:

values = Value.objects.filter(platform__id=platform.id)

Every time you call get, it's adding a where statement upon the filter statement and hit the database to fetch the results, so you don't gain anything in terms of performance.

By the way, Value.objects.get(Q(attribute__id=attribute.id) & Q(platform__id=platform.id)) is the same as:

Value.objects.get(attribute=attribute, platform=platform)

which is more readable.

Upvotes: 2

Related Questions