2009-11-06 3 views
1

У меня проблемы с производительностью, потому что я делаю много запросов, которые я не уверен, как уменьшить.оптимизировать этот код django?

user_item_rel_set - это отношение m2m между пользователем и элементами, показывающее, сколько пользователь заплатил за определенный предмет. Каждый элемент может иметь несколько пользователей и покупателей, и я пытаюсь получить отношение m2m для определенного пользователя.

 # find anything that you bought or used and how much you paid for it 
     u = User.objects.get(id=self.uid) 
     t = self.list.filter(user_item_rel__user__exact=u) 
     y = self.list.filter(buyer_item_rel__buyer__exact=u) 

     items = t | y 
     items = items.distinct() 
     u = User.objects.get(id=self.uid) 
     for t in items: 
      try: 
       t.price = t.user_item_rel_set.get(user=u).payment_amount 
      except: 
       t.price = -1 * t.buyer_item_rel_set.get(buyer=u).payment_amount 
     return items 

и в другом случае

for i in new_list: 
     if str(i.tag) not in x: 
      x[str(i.tag)] = 0 

     if houseMode == 0: 
      x[str(i.tag)] += float(i.user_item_rel_set.get(user__id__exact=self.uid).payment_amount) 
     else: 
      x[str(i.tag)] += float(i.price) 

ответ

1

дополнительный код из модели поможет, потому что это трудно понять, что QuerySet «Позиции» содержит.

Я постараюсь помочь в любом случае ...

Потому что вы смоделировали отношения между пользователями и элементами, нет необходимости перебирать каждый пункт в этом QuerySet, когда вы можете просто выбрать подмножество, которые являются Вам интересно.

Опять же, у меня немного трудностей следующей логики приложения, но я думаю, что ваши запросы могут быть сведены к чему-то такого рода:

# Find all the items where this user is the "user" 
user_items = items.filter(user_item_rel_set__user=u) 

# Find all the items where this user is the "buyer" 
buyer_items = items.filter(user_item_rel_set__buyer=u) 

Я не совсем понимаю, почему вы назначаете эти значения равны «t.price» в цикле или я буду расширять этот код.

Если это не помогает вашей работе, я рекомендую dumping your SQL queries to the console, чтобы вы могли точно видеть, что происходит за ORM. В логике, подобной этому, для получения вашего расчета не должно быть больше нескольких операторов SQL.

Кроме того, как правило, плохая идея использовать типы данных с плавающей точкой (float) в любом месте в непосредственной близости от денежной ценности. Типы данных с плавающей запятой, как правило, предназначены для научных приложений, где производительность важнее точности. Если вы имеете дело с деньгами, точность почти всегда более важна, чем производительность, поэтому вы используете тип данных, способный к точному представлению, например, decimal.Decimal везде.

Редактировать

Учитывая замечания, я рекомендую начать свой запрос с «отношения» объект вместо пункта. Так как ваш образец не сказать мне имя этого класса, я буду считать, что называется UserItem:

from django.db.models import Q 
from decimal import Decimal 

price = Decimal('0') 

# Get all UserItems where this user is the user or buyer 
interesting_items = UserItem.objects.filter((Q(user=u) | Q(buyer=u))) 
for ii in interesting_items: 
    if ii.user == u: 
     price += ii.payment_amount 
    elif ii.buyer == u: 
     price -= ii.payment_amount 
    else: 
     assert False, "Oops, this shouldn't happen" 

# Do something with 'price'... 

Джанго «Q» объект позволяет получить немного больше зернистый с запросами. Если вам нужно фильтровать на основе какого-либо атрибута элемента, бросьте туда тоже.

Часть, которая все еще меня смущает в ваших примерах, почему вы назначаете «цену» объекту объекта, когда ясно, что многие пользователи будут делиться этим предметом.

Edit 2

Вы также можете использовать aggregation API позволить СУБД вычислить сумму, если это все, что вас интересует:

from django.db.models import Sum 
buyer_price = UserItem.objects.filter(item=i, user=u).aggregate(
       Sum('payment_amount'))['payment_amount__sum'] 
+0

Так товара имеет цену, и его М2М отношения (user_item_rel), сколько пользователь заплатил за этот элемент. У меня есть список элементов, в которых задействован пользователь (именно тот код, который у вас есть), и я пытаюсь получить, сколько пользователь заплатил за каждый элемент, хотя я не могу этого сделать, не забивая базу данных для каждого отдельного элемента , – victor

+0

Итак, поле «payment_amount» хранится в объекте отношений между пользователем и элементом? Я предполагаю, что отношение m2m имеет свою собственную модель? –

+0

Да, это так. – victor

Смежные вопросы