144 lines
4.8 KiB
Python
144 lines
4.8 KiB
Python
|
import re
|
|||
|
|
|||
|
from django.conf import settings
|
|||
|
from django.contrib.auth import authenticate, login, logout, REDIRECT_FIELD_NAME
|
|||
|
from django.contrib.auth.decorators import login_required
|
|||
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
|||
|
from django.contrib.auth.models import User
|
|||
|
from django.shortcuts import render, redirect
|
|||
|
from django.views import View
|
|||
|
from django.views.generic import ListView, DetailView
|
|||
|
from django.views.generic.detail import SingleObjectMixin
|
|||
|
|
|||
|
from gnnrec.kgrec import recall, rank
|
|||
|
from .models import Author, Paper
|
|||
|
|
|||
|
|
|||
|
class LoginView(View):
|
|||
|
|
|||
|
def get(self, request):
|
|||
|
if request.user.is_authenticated:
|
|||
|
return redirect('rank:index')
|
|||
|
return render(request, 'rank/login.html', {'login_url': request.get_full_path()})
|
|||
|
|
|||
|
def post(self, request):
|
|||
|
username = request.POST.get('username')
|
|||
|
password = request.POST.get('password')
|
|||
|
user = authenticate(request, username=username, password=password)
|
|||
|
if user is not None:
|
|||
|
login(request, user)
|
|||
|
return redirect(self.get_redirect_url())
|
|||
|
else:
|
|||
|
return render(request, 'rank/login.html', {'message': '用户名或密码错误'})
|
|||
|
|
|||
|
def get_redirect_url(self):
|
|||
|
return self.request.POST.get(REDIRECT_FIELD_NAME) \
|
|||
|
or self.request.GET.get(REDIRECT_FIELD_NAME, 'rank:index')
|
|||
|
|
|||
|
|
|||
|
def logout_view(request):
|
|||
|
logout(request)
|
|||
|
return redirect('rank:login')
|
|||
|
|
|||
|
|
|||
|
class RegisterView(View):
|
|||
|
|
|||
|
def get(self, request):
|
|||
|
return render(request, 'rank/register.html')
|
|||
|
|
|||
|
def post(self, request):
|
|||
|
username = request.POST.get('username')
|
|||
|
password = request.POST.get('password')
|
|||
|
password2 = request.POST.get('password2')
|
|||
|
name = request.POST.get('name')
|
|||
|
email = request.POST.get('email')
|
|||
|
message = ''
|
|||
|
|
|||
|
if not re.fullmatch('[0-9A-Za-z_]+', username):
|
|||
|
message = '用户名只能包含字母、数字和下划线'
|
|||
|
elif User.objects.filter(username=username).exists():
|
|||
|
message = '用户名已存在'
|
|||
|
elif password != password2:
|
|||
|
message = '两次密码不一致'
|
|||
|
|
|||
|
if message:
|
|||
|
return render(request, 'rank/register.html', {'message': message})
|
|||
|
User.objects.create_user(username, email, password, first_name=name)
|
|||
|
return redirect('rank:login')
|
|||
|
|
|||
|
|
|||
|
@login_required
|
|||
|
def index(request):
|
|||
|
return render(request, 'rank/index.html')
|
|||
|
|
|||
|
|
|||
|
# 召回和学者排名模块上下文对象,在RankConfig.ready()中初始化
|
|||
|
recall_ctx = None
|
|||
|
rank_ctx = None
|
|||
|
|
|||
|
|
|||
|
class SearchPaperView(LoginRequiredMixin, ListView):
|
|||
|
template_name = 'rank/search_paper.html'
|
|||
|
|
|||
|
def get_queryset(self):
|
|||
|
if not self.request.GET.get('q'):
|
|||
|
return Paper.objects.none()
|
|||
|
_, pid = recall.recall(recall_ctx, self.request.GET['q'], settings.PAGE_SIZE)
|
|||
|
return sorted(Paper.objects.filter(id__in=pid), key=lambda p: pid.index(p.id))
|
|||
|
|
|||
|
def get_context_data(self, **kwargs):
|
|||
|
context = super().get_context_data(**kwargs)
|
|||
|
context['q'] = self.request.GET.get('q', '')
|
|||
|
return context
|
|||
|
|
|||
|
|
|||
|
class PaperDetailView(LoginRequiredMixin, DetailView):
|
|||
|
model = Paper
|
|||
|
|
|||
|
|
|||
|
# 参考 https://docs.djangoproject.com/en/3.2/topics/class-based-views/mixins/#using-singleobjectmixin-with-listview
|
|||
|
class AuthorDetailView(LoginRequiredMixin, SingleObjectMixin, ListView):
|
|||
|
template_name = 'rank/author_detail.html'
|
|||
|
paginate_by = settings.PAGE_SIZE
|
|||
|
|
|||
|
def get(self, request, *args, **kwargs):
|
|||
|
self.object = self.get_object(queryset=Author.objects.all())
|
|||
|
return super().get(request, *args, **kwargs)
|
|||
|
|
|||
|
def get_queryset(self):
|
|||
|
return self.object.papers.order_by('-n_citation')
|
|||
|
|
|||
|
def get_context_data(self, **kwargs):
|
|||
|
context = super().get_context_data(**kwargs)
|
|||
|
context['author'] = self.object
|
|||
|
return context
|
|||
|
|
|||
|
|
|||
|
class SearchAuthorView(LoginRequiredMixin, ListView):
|
|||
|
template_name = 'rank/search_author.html'
|
|||
|
|
|||
|
def get_queryset(self):
|
|||
|
if not self.request.GET.get('q'):
|
|||
|
return Author.objects.none()
|
|||
|
return Author.objects.filter(name=self.request.GET['q'])
|
|||
|
|
|||
|
def get_context_data(self, **kwargs):
|
|||
|
context = super().get_context_data(**kwargs)
|
|||
|
context['q'] = self.request.GET.get('q', '')
|
|||
|
return context
|
|||
|
|
|||
|
|
|||
|
class AuthorRankView(LoginRequiredMixin, ListView):
|
|||
|
template_name = 'rank/author_rank.html'
|
|||
|
|
|||
|
def get_queryset(self):
|
|||
|
if not self.request.GET.get('q'):
|
|||
|
return Author.objects.none()
|
|||
|
_, aid = rank.rank(rank_ctx, self.request.GET['q'])
|
|||
|
return sorted(Author.objects.filter(id__in=aid), key=lambda a: aid.index(a.id))
|
|||
|
|
|||
|
def get_context_data(self, **kwargs):
|
|||
|
context = super().get_context_data(**kwargs)
|
|||
|
context['q'] = self.request.GET.get('q', '')
|
|||
|
return context
|