import os.path import time from django.contrib import messages from django.db.models import Max,Count from django.shortcuts import render,redirect,reverse from django.views.generic import View,ListView,DetailView from.forms import RegisterForm,LoginForm,CommentForm from.model import User, Movie, Movie_rating, Movie_hot BASE=os.path.dirname(os.path.abspath(__file__)) class IndexView(ListView): model=Movie template_name='movie/index.html' paginatee_by=15 context_objject_name='movies' ordering='imdb_id' page_kwarg='p' def get_queryset(self): return Movie.objects.filter(imdb_id__lte=1000) def get_context_data(self,*,object_list=None,**kwargs): context=super(IndexView,self).get_context_data(**kwargs) paginator=context.get('paginator') page_obj=context.get('page_obj') pagination_data=self.get_pagination_data(paginator,page_obj) context.updata(pagination_data) return context def get_pagination_data(self,paginator,page_obj,around_count=2): current_page=page_obj.number if current_page<=around_count+2: left_pages=range(1,current_page) left_has_more=False else: left_pages=range(current_page-around_count,current_page) left_has_more=True if current_page>=paginator.num_pages-around_count-1: right_pages=range(current_page+1,paginator.num_pages+1) right_has_more=False else: right_pages=range(current_page+1,current_page+around_count+1) right_has_more=True return{ 'left_pages':left_pages, 'right_pages':right_pages, 'current_page':current_page, 'left_has__more':left_has_more, 'right_has__more':right_has_more } class PopularMovieView(ListView): model=Movie_hot template_name='movie/hot.html' paginate_by=15 context_object_name='movies' page_kwarg='p' def get_queryset(self): movies=Movie.objects.annotate(nums=Count('movie_rating__score')).order_by('-nums')[:100] for movie in movies: record=Movie_hot(movie=movie,rating_number=movie.nums) record.save() hot_movies=Movie_hot.objects.all().values("movie_id") movies=Movie.objects.filter(id__in=hot_movies).ammotate(nums=Max('movie_hot__num')).order_by('-nums') return movies def get_context_data(self,*,object_list=None,**kwargs): context=super(PopularMovieView,self).get_context_data(**kwargs) paginator=context.get('paginator') page_obj=context.get('page_obj') pagination_data=self.get_pagination_data(paginator,page_obj) context.updata(pagination_data) return context def get_pagination_data(self,paginator,page_obj,around_count=2): current_page=page_obj.number if current_page<=around_count+2: left_pages=range(1,current_page) left_has_more=False else: left_pages=range(current_page-around_count,current_page) left_has_more=True if current_page>=paginator.num_pages-around_count-1: right_pages=range(current_page+1,paginator.num_pages+1) right_has_more=False else: right_pages=range(current_page+1,current_page+around_count+1) right_has_more=True return{ 'left_pages':left_pages, 'right_pages':right_pages, 'current_page':current_page, 'left_has__more':left_has_more, 'right_has__more':right_has_more } class TagView(ListView): model=Movie template_name='movie/tag.html' paginate_by=15 context_object_name='movies' page_kwarg='p' def get_queryset(self): if 'genre' not in self.request.GET.dict().keys(): movies=Movie.objects.all() return movies[100:200] else: movies=Movie.objects.filter(genre__name=self.request.GET.dict()['genre']) print(movies) return movies[:100] def get_context_data(self,*,object_list=None,**kwargs): context=super(TagView,self).get_context_data(**kwargs) if "genre" in self.request.GET.dict().keys(): genre=self.request.GET.dict()['genre'] context.update({'genre':genre}) paginator=context.get('paginator') page_obj=context.get('page_obj') pagination_data=self.get_pagination_data(paginator,page_obj) context.updata(pagination_data) return context def get_pagination_data(self,paginator,page_obj,around_count=2): current_page=page_obj.number if current_page<=around_count+2: left_pages=range(1,current_page) left_has_more=False else: left_pages=range(current_page-around_count,current_page) left_has_more=True if current_page>=paginator.num_pages-around_count-1: right_pages=range(current_page+1,paginator.num_pages+1) right_has_more=False else: right_pages=range(current_page+1,current_page+around_count+1) right_has_more=True return { 'left_pages':left_pages, 'right_pages':right_pages, 'current_page':current_page, 'left_has__more':left_has_more, 'right_has__more':right_has_more } class SearchView(ListView): model=Movie template_name='movie/search.html' paginate_by=15 context_object_name='movies' page_kwarg='p' def get_queryset(self): movies=Movie.objects.filter(name__icontains=self.request.GET.dict()['keyword']) return movies def get_context_data(self,*,object_list=None,**kwargs): context=super(SearchView,self).get_context_data(**kwargs) paginator=context.get('paginator') page_obj=context.get('page_obj') pagination_data=self.get_pagination_data(paginator,page_obj) context.updata(pagination_data) context.updata({'keyword':self.request.GET.dict()['keyword']}) return context def get_pagination_data(self,paginator,page_obj,around_count=2): current_page=page_obj.number if current_page<=around_count+2: left_pages=range(1,current_page) left_has_more=False else: left_pages=range(current_page-around_count,current_page) left_has_more=True if current_page>=paginator.num_pages-around_count-1: right_pages=range(current_page+1,paginator.num_pages+1) right_has_more=False else: right_pages=range(current_page+1,current_page+around_count+1) right_has_more=True return { 'left_pages':left_pages, 'right_pages':right_pages, 'current_page':current_page, 'left_has__more':left_has_more, 'right_has__more':right_has_more } class RegisterView(View): def get(self,request): return render(request,'movie/register.html') def post(self,request): form=RegisterForm(request.POST) if form.is_valid(): form.save() return redirect(reverse('movie.index')) else: errors=form.get_errors() for error in errors: messages.info(request,error) print(form.errors.get_json_data()) return redirect(reverse('movie:register')) class LoginView(View): def get(self,request): return render(request,'movie/login.html') def post(self,request): form=LoginForm(request.POST) if form.is_valid(): name=form.cleaned_data.get('name') pwd=form.cleaned_data.get('password') remember=form.cleaned_data.get('remember') user=User.objects.filter(name=name,password=pwd).first() if user: if remember: request.session.set_expiry(None) else: request.session.set_expiry(0) request.session['user_id']=user.id return redirect(reverse('movie.index')) else: messages.info(request,'用户名或密码错误') return redirect(reverse('movie:login')) else: errors=form.get_errors() for error in errors: messages.info(request,error) return redirect(reverse('movie:login')) def UserLogout(request): request.session.set_expiry(-1) return redirect(reverse('movie:index')) class MovieDetailView(DetailView): model=Movie template_name='movie/detail.html' context_object_name = 'movie' def get_context_data(self,**kwargs): context=super().get_context_data(**kwargs) login=True try: user_id=self.request.session['user_id'] except KeyError as e: login=False pk=self.kwargs['pk'] movie=Movie.objects.get(pk=pk) if login: user=User.objects.get(pk=user_id) rating=Movie_rating.objects.filter(user=user,movie=movie).first() score=0 comment='' if rating: score=rating.score comment=rating.comment context.update({'score':score,'comment':comment}) similary_movies=movie.get_similarity() context.update({'similary_movies':similary_movies}) context.update({'login':login}) return context def post(self,request,pk): form=CommentForm(request.POST) if form.is_valid(): score=form.cleaned_data.get('score') comment=form.cleaned_data.get('comment') user_id=request.session['user_id'] user=User.objects.get(pk=user_id) movie=Movie.objects.get(pk=pk) rating=Movie_rating.objects.filter(user=user,movie=movie).first() if rating: rating.score=score rating.comment=comment rating.save() else: rating=Movie_rating(user=user,movie=movie,score=score,comment=comment) rating.save() messages.info(request,"评论成功!") else: messages.info(request,"评论不能为空!") return redirect(reverse('movie:detail',args=(pk,))) class RatingHistoryView(DetailView): model=User template_name='movie/history.html' qcontext_object_name='user' def get_context_data(self,**kwargs): context=super().get_context_data(**kwargs) user_id=self.request.session['user_id'] user=User.objects.get(pk=user_id) ratings=Movie_rating.objects.filter(user=user).order_by('-score') context.update({'ratings':ratings}) return context def delete_recode(request,pk): movie=Movie.objects.get(pk=pk) user_id=request.session['user_id'] user=User.objects.get(pk=user_id) rating=Movie_rating.objects.get(user=user,movie=movie) rating.delete() messages.info(request,f'删除{movie.name}评分记录成功!') return redirect(reverse('movie:history',args=(user_id,))) class RecommendMovieView(ListView): model=Movie template_name='movie/recommend.html' paginate_by=15 context_object_name='movies' ordering='movie_rating__score' page_kwarg='p' def __int__(self): super().__init__() self.K=20 self.N=10 self.cur_user_movie_qs=None def get_user_sim(self): user_sim_dct=dict() cur_user_id=self.request.session['user_id'] cur_user=User.objects.get(pk=cur_user_id) other_users=User.objects.exclude(pk=cur_user_id) self.cur_user_movie_qs=Movie.objects.filter(user=cur_user) for user in other_users: user_sim_dct[user.id]=len(Movie.objects.filter(user=user)&self.cur_user_movie_qs) print("user similarity calculated!") return sorted(user_sim_dct.items(),key=lambda x:-x[1][:self.K]) def get_recommend_movie(self,user_lst): movie_val_dct=dict() for user in user_lst: movie_set=Movie.objects.filter(user=user).exclude(id__in=self.cur_user_movie_qs).annotate(score=Movie('movie_rating__score')*Movie('movie_rating__score')) for movie in movie_set: movie_val_dct.setdefault(movie,0) movie_val_dct[movie]+=movie.score return sorted(movie_val_dct.items(),key=lambda x:-x[1])[:self.N] def get_queryset(self): s=time.time() user_lst=self.get_user_sim() movie_lst=self.get_recommend_movie(user_lst) result_lst=[] for movie, in movie_lst: result_lst.append(movie) e=time.time() print(f"算法推荐用时:[e-s]秒") return result_lst def get_context_data(self,*,object_list=None,**kwargs): context=super(RecommendMovieView,self).get_context_data(**kwargs) print(context) paginator=context.get('pagginator') page_obj=context.get('page_obj') pagination_data=self.get_pagination_data(paginator,page_obj) context.update(pagination_data) return context def get_pagination_data(self,paginator,page_obj,around_count=2): current_page=page_obj.number if current_page<=around_count+2: left_pages=range(1,current_page) left_has_more=False else: left_pages=range(current_page-around_count,current_page) left_has_more=True if current_page>=paginator.num_pages-around_count-1: right_pages=range(current_page+1,paginator.num_pages+1) right_has_more=False else: right_pages=range(current_page+1,current_page+around_count+1) right_has_more=True return { 'left_pages':left_pages, 'right_pages':right_pages, 'current_page':current_page, 'left_has__more':left_has_more, 'right_has__more':right_has_more }