forked from prlbkj9i7/wzy
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.
402 lines
14 KiB
402 lines
14 KiB
6 months ago
|
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
|
||
|
}
|