views.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. import json
  2. import logging
  3. from celery import states
  4. from django.conf import settings
  5. from django.contrib.auth.decorators import login_required
  6. from django.contrib.auth.mixins import LoginRequiredMixin
  7. from django.db.models import Avg, Count, F
  8. from django.http import HttpResponse
  9. from django.views.generic import DetailView, ListView
  10. from django.views.generic.list import MultipleObjectMixin
  11. from django_celery_results.models import TaskResult
  12. from games.tasks import update_roms
  13. from .models import Developer, Game, GameCollection, GameSystem, Genre, Publisher
  14. logger = logging.Logger(__name__)
  15. IN_PROGRESS_STATES = [states.PENDING, states.STARTED, states.RETRY]
  16. class RecentGameList(LoginRequiredMixin, ListView):
  17. model = Game
  18. paginate_by = 20
  19. queryset = Game.objects.order_by("-created")[:200]
  20. class LibraryGameList(ListView, LoginRequiredMixin):
  21. template_name = "games/game_library_list.html"
  22. model = Game
  23. paginate_by = 200
  24. def get_context_data(self, **kwargs):
  25. game_system_slug = self.request.GET.get("game_system")
  26. order_by = self.request.GET.get("order_by", "name")
  27. if order_by[0] == "-":
  28. order_by = order_by[1:]
  29. object_list = Game.objects.order_by(F(order_by).desc(nulls_last=True))
  30. else:
  31. object_list = Game.objects.order_by(F(order_by).asc(nulls_last=True))
  32. if game_system_slug:
  33. object_list = object_list.filter(
  34. game_system__retropie_slug=game_system_slug
  35. )
  36. context = super(LibraryGameList, self).get_context_data(
  37. object_list=object_list, **kwargs
  38. )
  39. return context
  40. class FilterableBaseListView(ListView, LoginRequiredMixin):
  41. def get_queryset(self, **kwargs):
  42. order_by = self.request.GET.get("order_by", "name")
  43. queryset = super().get_queryset(**kwargs)
  44. queryset = queryset.annotate(num_games=Count("game")).annotate(
  45. rating=Avg("game__rating")
  46. )
  47. if order_by[0] == "-":
  48. order_by = order_by[1:]
  49. queryset = queryset.order_by(F(order_by).desc(nulls_last=True))
  50. else:
  51. queryset = queryset.order_by(F(order_by).asc(nulls_last=True))
  52. return queryset
  53. class PublisherList(FilterableBaseListView):
  54. model = Publisher
  55. class DeveloperList(FilterableBaseListView):
  56. model = Developer
  57. class GenreList(FilterableBaseListView):
  58. model = Genre
  59. class GameDetail(DetailView, LoginRequiredMixin):
  60. model = Game
  61. class GamePlayDetail(DetailView, LoginRequiredMixin):
  62. template_name = "games/game_play_detail.html"
  63. model = Game
  64. class GameSystemList(ListView, LoginRequiredMixin):
  65. model = GameSystem
  66. class GameSystemDetail(DetailView, MultipleObjectMixin, LoginRequiredMixin):
  67. model = GameSystem
  68. paginate_by = 20
  69. def get_context_data(self, **kwargs):
  70. object_list = Game.objects.filter(game_system=self.get_object())
  71. context = super(GameSystemDetail, self).get_context_data(
  72. object_list=object_list, **kwargs
  73. )
  74. return context
  75. class GenreDetail(DetailView, MultipleObjectMixin, LoginRequiredMixin):
  76. model = Genre
  77. paginate_by = 20
  78. def get_context_data(self, **kwargs):
  79. object_list = Game.objects.filter(genre=self.get_object())
  80. context = super(GenreDetail, self).get_context_data(
  81. object_list=object_list, **kwargs
  82. )
  83. return context
  84. class PublisherDetail(DetailView, MultipleObjectMixin, LoginRequiredMixin):
  85. model = Publisher
  86. paginate_by = 20
  87. def get_context_data(self, **kwargs):
  88. object_list = Game.objects.filter(publisher=self.get_object())
  89. context = super(PublisherDetail, self).get_context_data(
  90. object_list=object_list, **kwargs
  91. )
  92. return context
  93. class DeveloperDetail(DetailView, MultipleObjectMixin, LoginRequiredMixin):
  94. model = Developer
  95. paginate_by = 20
  96. def get_context_data(self, **kwargs):
  97. object_list = Game.objects.filter(developer=self.get_object())
  98. context = super(DeveloperDetail, self).get_context_data(
  99. object_list=object_list, **kwargs
  100. )
  101. return context
  102. class GameCollectionList(ListView, LoginRequiredMixin):
  103. model = GameCollection
  104. class GameCollectionDetail(DetailView, LoginRequiredMixin):
  105. model = GameCollection
  106. def get_context_data(self, **kwargs):
  107. collection = self.get_object()
  108. order_by = self.request.GET.get("order_by", "release_date")
  109. object_list = collection.games.all()
  110. if order_by[0] == "-":
  111. order_by = order_by[1:]
  112. object_list = object_list.order_by(F(order_by).desc(nulls_last=True))
  113. else:
  114. object_list = object_list.order_by(F(order_by).asc(nulls_last=True))
  115. context = super(GameCollectionDetail, self).get_context_data(
  116. object_list=object_list, **kwargs
  117. )
  118. return context
  119. @login_required
  120. def trigger_rom_update(request):
  121. full_scan = request.GET.get("full_scan", False)
  122. if full_scan == "true":
  123. full_scan = True
  124. game_systems = request.GET.getlist("game_systems")
  125. if not game_systems:
  126. game_systems = list(settings.GAME_SYSTEM_DEFAULTS.keys())
  127. try:
  128. update_roms.delay(game_systems, full_scan=full_scan)
  129. except FileNotFoundError:
  130. return HttpResponse(
  131. json.dumps({"success": False, "msg": "Skyscraper is not installed"}),
  132. status=400,
  133. content_type="application/json",
  134. )
  135. return HttpResponse(
  136. json.dumps({"success": True, "msg": "Library scan started"}),
  137. status=200,
  138. content_type="application/json",
  139. )
  140. @login_required
  141. def library_update_status(request):
  142. update_task = TaskResult.objects.filter(
  143. task_name="games.tasks.update_roms",
  144. status__in=IN_PROGRESS_STATES,
  145. ).first()
  146. if not update_task:
  147. state = states.SUCCESS
  148. else:
  149. state = update_task.status
  150. return HttpResponse(
  151. json.dumps({"state": state}),
  152. status=200,
  153. content_type="application/json",
  154. )