Django: Лучше обрабатывать данные из models.py, чем делать это в views.py

В настоящее время я обрабатываю много информации в файле views.py, который кажется мне неподходящим местом для этого. Есть ли лучший/местный способ обработки этой информации? Это работает, но кажется, что я не использую Django в полную силу.

views.py - Здесь я выполняю всю обработку информации

def stats(request):
    user = request.user
    deck_list = Deck.objects.filter(user=request.user).annotate(
        win_count=Count('game', filter=Q(game__outcome='Win', game__user=request.user)),
        loss_count=Count('game', filter=Q(game__outcome='Loss', game__user=request.user)),
        draw_count=Count('game', filter=Q(game__outcome='Draw', game__user=request.user)),
        incomplete_count=Count('game', filter=Q(game__outcome='Incomplete', game__user=request.user)),
        count_1_7=Count('game', filter=Q(game__mull='1st 7', game__user=request.user)),
        count_2_7=Count('game', filter=Q(game__mull='2nd 7', game__user=request.user)),
        count_6=Count('game', filter=Q(game__mull='6', game__user=request.user)),
        count_5=Count('game', filter=Q(game__mull='5', game__user=request.user)),
        count_4=Count('game', filter=Q(game__mull='4', game__user=request.user)),
        count_3=Count('game', filter=Q(game__mull='3', game__user=request.user)),
        count_2=Count('game', filter=Q(game__mull='2', game__user=request.user)),
        count_1=Count('game', filter=Q(game__mull='1', game__user=request.user)),
    )

    # Totals for player
    total_game = Game.objects.filter(user=request.user).count()
    total_win = Game.objects.filter(user=request.user, outcome='Win').count()
    total_loss = Game.objects.filter(user=request.user, outcome='Loss').count()
    total_draw = Game.objects.filter(user=request.user, outcome='Draw').count()
    total_incomplete = Game.objects.filter(user=request.user, outcome='Incomplete').count()
    average_hand_size1_7 = Game.objects.filter(user=request.user, mull='1st 7').count()
    average_hand_size2_7 = Game.objects.filter(user=request.user, mull='2nd 7').count()
    average_hand_size6 = Game.objects.filter(user=request.user, mull='6').count()
    average_hand_size5 = Game.objects.filter(user=request.user, mull='5').count()
    average_hand_size4 = Game.objects.filter(user=request.user, mull='4').count()
    average_hand_size3 = Game.objects.filter(user=request.user, mull='3').count()
    average_hand_size2 = Game.objects.filter(user=request.user, mull='2').count()
    average_hand_size1 = Game.objects.filter(user=request.user, mull='1').count()

    average_hand = 0
    if total_game == 0:
        pass
    else:
        average_hand = (average_hand_size1_7 * 7 + average_hand_size2_7 * 7 + average_hand_size6 * 6 +
                        average_hand_size5 * 5 + average_hand_size4 * 4 + average_hand_size3 * 3 +
                        average_hand_size2 * 2 + average_hand_size1) / total_game

    context = {
        'user': user,
        'deck_list': deck_list,
        'total_game': total_game,
        'total_win': total_win,
        'total_loss': total_loss,
        'total_draw': total_draw,
        'total_incomplete': total_incomplete,
        'average_hand': average_hand,
    }
    return render(request, 'gametracker_app/stats.html', context=context)

models.py

Я думаю, что вы можете значительно сократить количество обращений к базе данных, если будете получать информацию, которую собираетесь обрабатывать, с помощью одного набора запросов, а затем обобщать ее в Python. Что-то вроде

from collections import Counter
...

   user_game_values =  Game.objects.filter(user=request.user
        ).values_list('mull','outcome')
   # returns a list of tuples (mull_value, outcome_value), one for each filtered Game

    mulls = Counter()
    outcomes =  Counter()
    for mull,outcome in user_game_values:
        mulls[mull] += 1
        outcomes[outcome] += 1

теперь вы можете получить, например,

average_hand_size1 = mulls['1']
total_loss = outcomes['Loss']

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

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

Установите django-debug-toolbar в своей среде разработки, если вы этого еще не сделали, хотя бы для того, чтобы вы могли отслеживать, как каждое представление забивает базу данных.

Вернуться на верх