You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

403 lines
14 KiB

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):
global user_id
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
}