ajoute une implémentation générique de RequestQuerySet.total_cost()
L'implémentation otpimisée n'est utilisée que si le backend est postgresql.
This commit is contained in:
parent
6804fa2376
commit
8ad4840833
|
@ -8,7 +8,7 @@ import os.path
|
|||
import datetime
|
||||
import decimal
|
||||
|
||||
from django.db import models, transaction
|
||||
from django.db import models, transaction, connections
|
||||
from django.utils.translation import ugettext_lazy as _, string_concat
|
||||
from django.core import validators
|
||||
from django.core.exceptions import ValidationError
|
||||
|
@ -84,25 +84,44 @@ def minimum_delivery_timedelta():
|
|||
|
||||
class RequestQueryset(utils.QuerySet):
|
||||
def total_cost(self):
|
||||
cost_function1 = '({1}.ppp * {0}.nb_pages + {1}.ppd)*{0}.copies'.format(
|
||||
Request._meta.db_table, profile.Profile._meta.db_table)
|
||||
cost_function2 = '''SELECT SUM(({1}.ppp * {0}.nb_pages + {1}.ppd)*{0}.copies) FROM {1}, {2}
|
||||
WHERE {1}.id = {2}.profileoptionchoice_id AND {2}.request_id = {0}.id'''.format(
|
||||
Request._meta.db_table, profile.ProfileOptionChoice._meta.db_table,
|
||||
Request._meta.get_field('choices').rel.through._meta.db_table)
|
||||
|
||||
qs1 = self \
|
||||
.prefetch_related(None) \
|
||||
.select_related(depth=0) \
|
||||
.extra(select={
|
||||
'base_profile_estimated_cost' : cost_function1,
|
||||
'choices_estimated_cost': cost_function2
|
||||
})
|
||||
qs1.query.join((Request._meta.db_table, profile.Profile._meta.db_table,
|
||||
Request._meta.get_field('base_profile').column,
|
||||
profile.Profile._meta.get_field('id').column))
|
||||
zero = decimal.Decimal(0)
|
||||
return sum([r.cost or ((r.base_profile_estimated_cost or zero)+(r.choices_estimated_cost or zero)) for r in qs1])
|
||||
# special case for Postgres so that it is fast in production
|
||||
if utils.qs_use_postgres(self):
|
||||
cost_function1 = '({1}.ppp * {0}.nb_pages + {1}.ppd)*{0}.copies'.format(
|
||||
Request._meta.db_table, profile.Profile._meta.db_table)
|
||||
cost_function2 = '''SELECT SUM(({1}.ppp * {0}.nb_pages + {1}.ppd)*{0}.copies) FROM {1}, {2}
|
||||
WHERE {1}.id = {2}.profileoptionchoice_id AND {2}.request_id = {0}.id'''.format(
|
||||
Request._meta.db_table, profile.ProfileOptionChoice._meta.db_table,
|
||||
Request._meta.get_field('choices').rel.through._meta.db_table)
|
||||
|
||||
qs1 = self \
|
||||
.prefetch_related(None) \
|
||||
.select_related(depth=0) \
|
||||
.extra(select={
|
||||
'base_profile_estimated_cost' : cost_function1,
|
||||
'choices_estimated_cost': cost_function2
|
||||
})
|
||||
qs1.query.join((Request._meta.db_table, profile.Profile._meta.db_table,
|
||||
Request._meta.get_field('base_profile').column,
|
||||
profile.Profile._meta.get_field('id').column))
|
||||
return sum([r.cost or ((r.base_profile_estimated_cost or zero)+(r.choices_estimated_cost or zero)) for r in qs1])
|
||||
else:
|
||||
# generic implementation working everywhere
|
||||
qs = self.select_related(depth=0) \
|
||||
.select_related('base_profile') \
|
||||
.prefetch_related(None) \
|
||||
.prefetch_related('choices') \
|
||||
.only('nb_pages', 'copies', 'base_profile__ppp',
|
||||
'base_profile__ppd', 'choices__ppp', 'choices__ppd')
|
||||
total_cost = zero
|
||||
for r in qs:
|
||||
ppp = r.base_profile.ppp
|
||||
ppd = r.base_profile.ppd
|
||||
for c in r.choices.all():
|
||||
ppp += c.ppp
|
||||
ppd += c.ppd
|
||||
total_cost += ((r.nb_pages * ppp) + ppd) * r.copies
|
||||
return total_cost
|
||||
|
||||
class Request(models.Model):
|
||||
COPYRIGHT_CHOICES = (
|
||||
|
|
|
@ -6,7 +6,7 @@ import time
|
|||
|
||||
import django.core.cache
|
||||
from django.core.urlresolvers import RegexURLPattern, RegexURLResolver
|
||||
from django.db import models
|
||||
from django.db import models, connections
|
||||
from django.db.models import query
|
||||
|
||||
def get_next_workable_day(today=None, hours=0, days=2, increment_hours=0, increment_days=1):
|
||||
|
@ -205,3 +205,6 @@ class QuerySet(models.query.QuerySet):
|
|||
@classmethod
|
||||
def as_manager(cls, ManagerClass=QuerySetManager):
|
||||
return ManagerClass(cls)
|
||||
|
||||
def qs_use_postgres(qs):
|
||||
return hasattr(connections[qs._db or 'default'], 'pg_version')
|
||||
|
|
Reference in New Issue