| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 |
- # mysite/views.py
- from django.views.generic import ListView, CreateView, UpdateView, DeleteView, DetailView
- from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
- from django.contrib.auth import logout
- from django.shortcuts import render, redirect, get_object_or_404
- from django.urls import reverse_lazy
- from django.db.models import Avg, Count
- from django.contrib import messages
- from .models import Musician, Song, Meloman, Rating, Album, Genre
- from .forms import MusicianForm, SongForm, RatingForm, RegistrationForm
- from django.views.generic import TemplateView
- # Регистрация
- def register(request):
- if request.method == 'POST':
- form = RegistrationForm(request.POST)
- if form.is_valid():
- form.save()
- messages.success(request, 'Регистрация прошла успешно! Теперь вы можете войти в систему.')
- return redirect('mysite:login')
- else:
- form = RegistrationForm()
- return render(request, 'mysite/register.html', {'form': form})
- # Выход из системы
- def custom_logout(request):
- logout(request)
- messages.success(request, 'Вы успешно вышли из системы')
- return redirect('mysite:login')
- # Главная страница со списком песен
- class SongListView(ListView):
- model = Song
- template_name = 'mysite/song_list.html'
- context_object_name = 'songs'
-
- def get_queryset(self):
- return Song.objects.select_related('album__musician', 'genre').annotate(
- avg_rating=Avg('rating__score'),
- ratings_count=Count('rating')
- )
-
- def get_context_data(self, **kwargs):
- context = super().get_context_data(**kwargs)
- search_query = self.request.GET.get('search', '')
- if search_query:
- context['songs'] = context['songs'].filter(
- title__icontains=search_query
- ) | context['songs'].filter(
- album__musician__name__icontains=search_query
- )
- context['search_query'] = search_query
- return context
- # Список исполнителей
- class MusicianListView(LoginRequiredMixin, ListView):
- model = Musician
- template_name = 'mysite/musician_list.html'
- context_object_name = 'musicians'
- paginate_by = 10
-
- def get_queryset(self):
- return Musician.objects.annotate(albums_count=Count('album'))
- class MusicianCreateView(LoginRequiredMixin, CreateView):
- model = Musician
- form_class = MusicianForm
- template_name = 'mysite/musician_form.html'
- success_url = reverse_lazy('mysite:musician_list')
-
- def form_valid(self, form):
- messages.success(self.request, 'Исполнитель успешно добавлен')
- return super().form_valid(form)
- class MusicianUpdateView(LoginRequiredMixin, UpdateView):
- model = Musician
- form_class = MusicianForm
- template_name = 'mysite/musician_form.html'
- success_url = reverse_lazy('mysite:musician_list')
-
- def form_valid(self, form):
- messages.success(self.request, 'Данные исполнителя обновлены')
- return super().form_valid(form)
- class MusicianDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
- model = Musician
- template_name = 'mysite/musician_confirm_delete.html'
- success_url = reverse_lazy('mysite:musician_list')
-
- def test_func(self):
- return self.request.user.is_superuser
-
- def delete(self, request, *args, **kwargs):
- messages.success(request, 'Исполнитель удален')
- return super().delete(request, *args, **kwargs)
- # Список песен для CRUD
- class SongListDataView(LoginRequiredMixin, ListView):
- model = Song
- template_name = 'mysite/song_list_data.html'
- context_object_name = 'songs'
-
- def get_queryset(self):
- return Song.objects.select_related('album__musician', 'genre').annotate(
- avg_rating=Avg('rating__score')
- )
- class SongCreateView(LoginRequiredMixin, CreateView):
- model = Song
- form_class = SongForm
- template_name = 'mysite/song_form.html'
- success_url = reverse_lazy('mysite:song_list_data')
-
- def form_valid(self, form):
- messages.success(self.request, 'Песня успешно добавлена')
- return super().form_valid(form)
- class SongUpdateView(LoginRequiredMixin, UpdateView):
- model = Song
- form_class = SongForm
- template_name = 'mysite/song_form.html'
- success_url = reverse_lazy('mysite:song_list_data')
-
- def form_valid(self, form):
- messages.success(self.request, 'Данные песни обновлены')
- return super().form_valid(form)
- class SongDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
- model = Song
- template_name = 'mysite/song_confirm_delete.html'
- success_url = reverse_lazy('mysite:song_list_data')
-
- def test_func(self):
- return self.request.user.is_superuser
- # Список меломанов
- class MelomanListView(LoginRequiredMixin, ListView):
- model = Meloman
- template_name = 'mysite/meloman_list.html'
- context_object_name = 'melomans'
-
- def get_queryset(self):
- return Meloman.objects.annotate(
- ratings_count=Count('rating'),
- avg_score=Avg('rating__score')
- )
-
- def dispatch(self, request, *args, **kwargs):
- if not request.user.is_superuser:
- return redirect('mysite:song_list')
- return super().dispatch(request, *args, **kwargs)
- # Профиль меломана
- class MelomanProfileView(LoginRequiredMixin, DetailView):
- model = Meloman
- template_name = 'mysite/profile.html'
- context_object_name = 'meloman'
-
- def get_object(self):
- try:
- return Meloman.objects.get(user=self.request.user)
- except Meloman.DoesNotExist:
- return None
-
- def get_context_data(self, **kwargs):
- context = super().get_context_data(**kwargs)
- meloman = self.get_object()
- if meloman:
- context['total_ratings'] = meloman.rating_set.count()
- context['avg_user_rating'] = meloman.rating_set.aggregate(Avg('score'))['score__avg']
- context['favorite_genres'] = meloman.preference_set.select_related('genre').all()
- context['age'] = meloman.age
- context['recent_ratings'] = meloman.rating_set.select_related('song').order_by('-rating_date')[:5]
- return context
- # Оценка песни
- def rate_song(request, song_id):
- if not request.user.is_authenticated:
- return redirect('mysite:login')
-
- song = get_object_or_404(Song, pk=song_id)
-
- try:
- meloman = Meloman.objects.get(user=request.user)
- except Meloman.DoesNotExist:
- messages.error(request, 'У вас нет профиля меломана. Обратитесь к администратору.')
- return redirect('mysite:song_list')
-
- rating, created = Rating.objects.get_or_create(
- meloman=meloman,
- song=song,
- defaults={'score': 5}
- )
-
- if request.method == 'POST':
- form = RatingForm(request.POST, instance=rating)
- if form.is_valid():
- form.save()
- messages.success(request, f'Оценка для "{song.title}" сохранена!')
- return redirect('mysite:song_list')
- else:
- form = RatingForm(instance=rating)
-
- return render(request, 'mysite/rate_song.html', {'form': form, 'song': song})
- from django.db import connection
- class SongDetailsView(ListView):
- """Использование представления song_details_view"""
- template_name = 'mysite/song_details.html'
- context_object_name = 'songs'
-
- def get_queryset(self):
- with connection.cursor() as cursor:
- cursor.execute("""
- SELECT song_id, title, musician_name, album_name,
- genre_name, duration_sec, avg_rating, ratings_count
- FROM song_details_view
- ORDER BY avg_rating DESC NULLS LAST
- """)
- columns = [col[0] for col in cursor.description]
- return [dict(zip(columns, row)) for row in cursor.fetchall()]
-
- class RecommendationsView(LoginRequiredMixin, TemplateView):
- """Использование функции recommend_songs"""
- template_name = 'mysite/recommendations.html'
-
- def get_context_data(self, **kwargs):
- context = super().get_context_data(**kwargs)
-
- try:
- meloman = Meloman.objects.get(user=self.request.user)
- meloman_id = meloman.meloman_id
- except Meloman.DoesNotExist:
- context['recommendations'] = []
- context['error'] = 'Профиль меломана не найден'
- return context
-
- with connection.cursor() as cursor:
- cursor.execute("""
- SELECT * FROM recommend_songs(%s, %s)
- """, [meloman_id, 10])
-
- columns = [col[0] for col in cursor.description]
- recommendations = [dict(zip(columns, row)) for row in cursor.fetchall()]
-
- context['recommendations'] = recommendations
- return context
|