オファー価格の平均を表示する必要があります。問題は、多対多フィールドの組み合わせの平均を計算する必要があることです。私はこのすべてをページングしなければならない。平均を計算するとパフォーマンスが低下します
私はすでにそれをしました。問題はパフォーマンスが悪いことです。解決方法を探しています。
モデルは次のようになります。
class Offer(models.Model):
price = DecimalField(max_digits=10, decimal_places=2)
quantity = PositiveIntegerField()
product = ForeignKey(Product)
qualifiers = ManyToManyField(Qualifier)
平均値を計算するために、関連するコードはこれです:
def get_average(product, qualifiers, users=None):
offers = Offer.objects.filter(product=product)
if users is not None:
offers = offers.filter(user__in=users)
for qualifier in qualifiers:
offers = offers.filter(qualifiers=qualifier)
if not offers.count():
return None
offers = offers.aggregate(
quantity_x_price_sum=Sum(F('quantity') * F('price'), output_field=FloatField()),
quantity_total=Sum('quantity')
)
# Weighted average
return offers['quantity_x_price_sum']/offers['quantity_total']
def get_averages(product, limit=20, users=None):
averages = []
colors = product.qualifiers.filter(type=1)
sizes = product.qualifiers.filter(type=2)
other = product.qualifiers.filter(type=3)
qualifiers = [colors, sizes, other]
combinations = itertools.product(*qualifiers)
for combination in combinations:
average = get_average(product, combination, users)
if average is not None:
averages.append(average)
if len(averages) == limit:
return averages
return averages
主な問題は、itertools.product(*修飾子)です。それは何百もの組み合わせを生み出すことができます。 そして、len(prices)== limitになるまでは、それぞれを反復してクエリを実行する必要があります。
助けを歓迎します。ありがとう。
最初に、あなたの組み合わせを取得してforループに渡すために 'combinations = list(itertools.product(* qualifiers))'リストを作成しています。これに対する改良は、ジェネレータ 'combined = itertools.product(* qualifiers)'を生成することです。そして、forループに組み合わせを渡すことができます。これは、リストを生成するためのオーバーヘッドを減らし、それを繰り返します。 –