Ich muss Durchschnittswerte der Angebotspreise zeigen. Das Problem ist, dass ich die Durchschnittswerte für Kombinationen eines Viele-zu-Viele-Feldes berechnen muss. Ich muss das alles auch pagen.Schlechte Leistung bei der Berechnung der Durchschnittswerte
Ich habe es schon getan. Das Problem ist, dass es eine schlechte Leistung hat, und ich suche nach einer Möglichkeit, es zu lösen.
Das Modell sieht wie folgt aus:
class Offer(models.Model):
price = DecimalField(max_digits=10, decimal_places=2)
quantity = PositiveIntegerField()
product = ForeignKey(Product)
qualifiers = ManyToManyField(Qualifier)
Der entsprechende Code, um die Mittelwerte zu berechnen, ist dies:
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
Das Hauptproblem in itertools.product ist (* Qualifier). Das kann Hunderte von Kombinationen erzeugen. Und bis len (prices) == limit, muss es über jeden von ihnen iterieren und die Abfrage ausführen.
Jede Hilfe ist willkommen. Vielen Dank.
Auf den ersten Blick erstellen Sie eine Liste 'combinations = list (itertools.product (* qualifiers))', um Ihre Kombinationen zu erhalten und in eine for-Schleife zu überführen. Eine Verbesserung ist das Erstellen eines Generators 'combinations = itertools.product (* qualifiers)', dann können Sie Kombinationen in eine for-Schleife übergeben. Dies reduziert den Aufwand für die Erstellung einer Liste und iteriert sie dann. –