2016-01-15 6 views
0

модели:Django базы данных оптимизации

class Teamresult(models.Model): 
    event = models.ForeignKey(Event) 
    team_category = models.ForeignKey(Teamcategory) 
    team_place= models.IntegerField() 
    team_name = models.CharField(max_length=64) 
    athlete_team_place = models.IntegerField() 
    athlete_time = models.DurationField() 
    athlete_name = models.CharField(max_length=64) 
    counts = models.BooleanField() 
    class Meta: 
     unique_together = ('event', 'team_category', 'team_name', 'athlete_team_place') 
     ordering = ('event', 'team_category', 'team_place', 'athlete_team_place') 

class Teamcategory(models.Model): 
    name = models.CharField(max_length=50, unique=True) 
    slug = models.SlugField(unique=True) 

Я хочу, чтобы сделать список (или QuerySet, если это возможно) со следующим, только один элемент списка для каждого уникального team_category (для фильтрованного события):

[(<first category>, <top>, <winning team>, <total time>, <average time>), (<second category>, ...), ...] 

«top» относится к числу Counts = True результатов для этой категории.

Это код, который у меня есть до сих пор, это ужасный поход.

event_id = 1 
raw_team_results = Teamresult.objects.filter(event_id=event_id, counts=True).order_by('team_place', 'athlete_team_place') 
present_team_categories = Teamresult.objects.filter(event_id=event.id).values_list('team_category__name', flat=True) 
present_team_categories = set(sorted(present_team_categories)) 
team_categories = Teamcategory.objects.filter(name__in=present_team_categories) 
team_results = [] 
for team_category in team_categories: 
    winning_team = raw_team_results.get(team_category=team_category, team_place=1, athlete_team_place=1).team_name 
    top = raw_team_results.filter(team_category=team_category, team_name=winning_team).filter(counts=True).aggregate(Count('athlete_time'))['athlete_time__count'] 
    total_time = raw_team_results.filter(team_category=team_category, team_name=winning_team).filter(counts=True).aggregate(Sum('athlete_time'))['athlete_time__sum'] 
    avg_microseconds = raw_team_results.filter(team_name=winning_team).filter(counts=True).aggregate(Avg('athlete_time'))['athlete_time__avg'] 
    raw_avg_time = timedelta(microseconds = avg_microseconds) 
    avg_time = raw_avg_time - timedelta(microseconds=raw_avg_time.microseconds) 
    team_results.append((team_category, top, winning_team, total_time, avg_time)) 

Это работает, но помимо того, что бардак, каждый цикл для цикла попадает к базе данных в 4 раза, хотя я бы подумал, что это нужно только данные, которые я уже получил ранее с raw_team_results.

Ясно, что я новичок в этом, любые предложения, чтобы сделать это лучше?

ответ

1

Модели выглядят довольно хорошо для меня. Чтобы сделать код более DRY, попробуйте поставить свою тяжелую технику менеджерам моделей:

class TeamcategoryQuerySet(models.QuerySet): 
    def of_results(self, results): 
     return self.filter(pk__in=results.values('team_category').distinct()) 


class TeamresultQuerySet(models.QuerySet): 
    def winning_team_details(self, categories): 
     return (self 
       .filter(
        team_category=category, team_place=1, 
        athlete_team_place=1, counts=True) 
       .annotate(
        top=Count('athlete_time'), 
        total=Sum('athlete_time'), 
        avg=Avg('athlete_time'), 
       )[0] 

    def of_event(self, event) 
     results = self.filter(event=event, counts=True) 
     for team_category in Teamcategory.objects.of_results(results): 
      winner = results.winning_team_details(category) 
      yield (category, winner['top'], winner['team_name'], 
        winner['total'], winner['avg']) 


class Teamcategory(models.Model): 
    # fields 
    objects = TeamcategoryQuerySet.as_manager() 


class Teamresult(models.Model): 
    # fields 
    objects = TeamresultQuerySet.as_manager() 


def get_event_results(event) 
    return Teamresult.objects.of_event(event) 
+0

Это выглядит довольно круто, я сделаю снимок. Где обычно хранятся классы QuerySet, в models.py? Спасибо! – user3449833

+0

Да, лучше держать менеджеров близко к моделям, так что вам не нужно уходить. –

+0

ОШИБКА: объект «TeamcategoryQuerySet» не имеет атрибутов «объекты» – user3449833