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 в своей среде разработки, если вы этого еще не сделали, хотя бы для того, чтобы вы могли отслеживать, как каждое представление забивает базу данных.