hw3 - Введены типы данных в models.py, сайт переписан под django модели - DB переведена на PostgreSQL - Переписан docker compose файл, настроены network и volume - Добавлена команда генерации рандомных данных в db hw4 - Добавлены формы login, signup, logout, profile - Добавлены вопросы и ответы и их модели и формы hw5 - Добавлена загрузка и отображение аватарок - Добавлены лайки и дизайки, отметка правильного ответа
423 lines
8.5 KiB
Python
423 lines
8.5 KiB
Python
from django.shortcuts import render, get_object_or_404
|
|
from django.core.paginator import Paginator
|
|
from django.contrib.auth import login as auth_login, logout as auth_logout
|
|
from django.shortcuts import redirect
|
|
from django.utils.http import url_has_allowed_host_and_scheme
|
|
from django.contrib.auth.decorators import login_required
|
|
from django.http import JsonResponse
|
|
from django.views.decorators.http import require_POST
|
|
|
|
from .models import (
|
|
Question,
|
|
Tag,
|
|
Answer,
|
|
QuestionReaction,
|
|
AnswerReaction
|
|
)
|
|
|
|
from .forms import (
|
|
LoginForm,
|
|
SignupForm,
|
|
ProfileForm,
|
|
AskForm,
|
|
AnswerForm
|
|
)
|
|
|
|
|
|
def index(request):
|
|
|
|
tag_name = request.GET.get('tag')
|
|
|
|
questions = Question.objects.all() \
|
|
.select_related('user') \
|
|
.prefetch_related('tags') \
|
|
.order_by('-created_at')
|
|
|
|
if tag_name:
|
|
questions = questions.filter(tags__name=tag_name)
|
|
|
|
paginator = Paginator(questions, 4)
|
|
|
|
page_number = request.GET.get('page', 1)
|
|
|
|
page_obj = paginator.get_page(page_number)
|
|
|
|
user_reactions = {}
|
|
|
|
if request.user.is_authenticated:
|
|
|
|
reactions = QuestionReaction.objects.filter(
|
|
user=request.user,
|
|
question__in=page_obj.object_list
|
|
)
|
|
|
|
user_reactions = {
|
|
reaction.question_id: reaction.positive
|
|
for reaction in reactions
|
|
}
|
|
|
|
hot_questions = Question.objects.order_by('-rating')[:4]
|
|
|
|
return render(request, 'core/index.html', {
|
|
'questions': page_obj.object_list,
|
|
'page_obj': page_obj,
|
|
'hot_questions': hot_questions,
|
|
'tags': Tag.objects.all(),
|
|
'tag': tag_name,
|
|
'user_reactions': user_reactions
|
|
})
|
|
|
|
|
|
def hot(request):
|
|
|
|
questions = Question.objects.all() \
|
|
.select_related('user') \
|
|
.prefetch_related('tags') \
|
|
.order_by('-rating')
|
|
|
|
paginator = Paginator(questions, 4)
|
|
|
|
page_number = request.GET.get('page', 1)
|
|
|
|
page_obj = paginator.get_page(page_number)
|
|
|
|
user_reactions = {}
|
|
|
|
if request.user.is_authenticated:
|
|
|
|
reactions = QuestionReaction.objects.filter(
|
|
user=request.user,
|
|
question__in=page_obj.object_list
|
|
)
|
|
|
|
user_reactions = {
|
|
reaction.question_id: reaction.positive
|
|
for reaction in reactions
|
|
}
|
|
|
|
return render(request, 'core/hot.html', {
|
|
'questions': page_obj.object_list,
|
|
'page_obj': page_obj,
|
|
'hot_questions': questions[:4],
|
|
'tags': Tag.objects.all(),
|
|
'user_reactions': user_reactions
|
|
})
|
|
|
|
|
|
def question(request):
|
|
|
|
question_id = request.GET.get('question_id')
|
|
|
|
question = get_object_or_404(
|
|
Question.objects.select_related('user')
|
|
.prefetch_related('tags', 'answers'),
|
|
id=question_id
|
|
)
|
|
|
|
if request.method == 'POST':
|
|
|
|
if not request.user.is_authenticated:
|
|
return redirect(
|
|
f'/login?next=/question?question_id={question_id}'
|
|
)
|
|
|
|
form = AnswerForm(request.POST)
|
|
|
|
if form.is_valid():
|
|
|
|
answer = form.save(
|
|
user=request.user,
|
|
question=question
|
|
)
|
|
|
|
return redirect(
|
|
f'/question?question_id={question.id}#answer-{answer.id}'
|
|
)
|
|
|
|
else:
|
|
|
|
form = AnswerForm()
|
|
|
|
question_reaction = None
|
|
|
|
answer_reactions = {}
|
|
|
|
if request.user.is_authenticated:
|
|
|
|
question_reaction = QuestionReaction.objects.filter(
|
|
question=question,
|
|
user=request.user
|
|
).first()
|
|
|
|
reactions = AnswerReaction.objects.filter(
|
|
user=request.user,
|
|
answer__question=question
|
|
)
|
|
|
|
answer_reactions = {
|
|
reaction.answer_id: reaction.positive
|
|
for reaction in reactions
|
|
}
|
|
|
|
return render(request, 'core/question.html', {
|
|
'question': question,
|
|
'answers': question.answers.all(),
|
|
'form': form,
|
|
'tags': Tag.objects.all(),
|
|
'question_reaction': question_reaction,
|
|
'answer_reactions': answer_reactions
|
|
})
|
|
|
|
|
|
def login(request):
|
|
|
|
next_url = request.GET.get('next', '/')
|
|
|
|
if request.method == 'POST':
|
|
|
|
form = LoginForm(request.POST)
|
|
|
|
if form.is_valid():
|
|
|
|
user = form.cleaned_data['user']
|
|
|
|
auth_login(request, user)
|
|
|
|
if not url_has_allowed_host_and_scheme(
|
|
next_url,
|
|
allowed_hosts={request.get_host()}
|
|
):
|
|
next_url = '/'
|
|
|
|
return redirect(next_url)
|
|
|
|
else:
|
|
|
|
form = LoginForm()
|
|
|
|
return render(request, 'core/login.html', {
|
|
'form': form,
|
|
'next': next_url,
|
|
'tags': Tag.objects.all()
|
|
})
|
|
|
|
|
|
def signup(request):
|
|
|
|
if request.method == 'POST':
|
|
|
|
form = SignupForm(request.POST, request.FILES)
|
|
|
|
if form.is_valid():
|
|
|
|
user = form.save()
|
|
|
|
auth_login(request, user)
|
|
|
|
return redirect('/')
|
|
|
|
else:
|
|
|
|
form = SignupForm()
|
|
|
|
return render(request, 'core/signup.html', {
|
|
'form': form,
|
|
'tags': Tag.objects.all()
|
|
})
|
|
|
|
|
|
def logout(request):
|
|
|
|
auth_logout(request)
|
|
|
|
return redirect(
|
|
request.META.get('HTTP_REFERER', '/')
|
|
)
|
|
|
|
|
|
@login_required
|
|
def profile(request):
|
|
|
|
if request.method == 'POST':
|
|
|
|
form = ProfileForm(
|
|
request.POST,
|
|
request.FILES,
|
|
user=request.user
|
|
)
|
|
|
|
if form.is_valid():
|
|
|
|
form.save()
|
|
|
|
return redirect('profile')
|
|
|
|
else:
|
|
|
|
form = ProfileForm(user=request.user)
|
|
|
|
return render(request, 'core/profile.html', {
|
|
'form': form,
|
|
'tags': Tag.objects.all()
|
|
})
|
|
|
|
|
|
@login_required
|
|
def ask(request):
|
|
|
|
if request.method == 'POST':
|
|
|
|
form = AskForm(request.POST)
|
|
|
|
if form.is_valid():
|
|
|
|
question = form.save(user=request.user)
|
|
|
|
return redirect(
|
|
f'/question?question_id={question.id}'
|
|
)
|
|
|
|
else:
|
|
|
|
form = AskForm()
|
|
|
|
return render(request, 'core/ask.html', {
|
|
'form': form,
|
|
'tags': Tag.objects.all()
|
|
})
|
|
|
|
|
|
@require_POST
|
|
@login_required
|
|
def question_react(request):
|
|
|
|
question_id = request.POST.get('question_id')
|
|
|
|
reaction_type = request.POST.get('type')
|
|
|
|
if reaction_type not in ['like', 'dislike']:
|
|
|
|
return JsonResponse({
|
|
'error': 'invalid type'
|
|
}, status=400)
|
|
|
|
question = get_object_or_404(
|
|
Question,
|
|
id=question_id
|
|
)
|
|
|
|
if QuestionReaction.objects.filter(
|
|
question=question,
|
|
user=request.user
|
|
).exists():
|
|
|
|
return JsonResponse({
|
|
'error': 'already reacted'
|
|
}, status=400)
|
|
|
|
positive = reaction_type == 'like'
|
|
|
|
QuestionReaction.objects.create(
|
|
question=question,
|
|
user=request.user,
|
|
positive=positive
|
|
)
|
|
|
|
if positive:
|
|
question.rating += 1
|
|
else:
|
|
question.rating -= 1
|
|
|
|
question.save()
|
|
|
|
return JsonResponse({
|
|
'rating': question.rating
|
|
})
|
|
|
|
|
|
@require_POST
|
|
@login_required
|
|
def answer_react(request):
|
|
|
|
answer_id = request.POST.get('answer_id')
|
|
|
|
reaction_type = request.POST.get('type')
|
|
|
|
if reaction_type not in ['like', 'dislike']:
|
|
|
|
return JsonResponse({
|
|
'error': 'invalid type'
|
|
}, status=400)
|
|
|
|
answer = get_object_or_404(
|
|
Answer,
|
|
id=answer_id
|
|
)
|
|
|
|
if AnswerReaction.objects.filter(
|
|
answer=answer,
|
|
user=request.user
|
|
).exists():
|
|
|
|
return JsonResponse({
|
|
'error': 'already reacted'
|
|
}, status=400)
|
|
|
|
positive = reaction_type == 'like'
|
|
|
|
AnswerReaction.objects.create(
|
|
answer=answer,
|
|
user=request.user,
|
|
positive=positive
|
|
)
|
|
|
|
if positive:
|
|
answer.rating += 1
|
|
else:
|
|
answer.rating -= 1
|
|
|
|
answer.save()
|
|
|
|
return JsonResponse({
|
|
'rating': answer.rating
|
|
})
|
|
|
|
|
|
@require_POST
|
|
@login_required
|
|
def mark_correct(request):
|
|
|
|
question_id = request.POST.get('question_id')
|
|
|
|
answer_id = request.POST.get('answer_id')
|
|
|
|
question = get_object_or_404(
|
|
Question,
|
|
id=question_id
|
|
)
|
|
|
|
answer = get_object_or_404(
|
|
Answer,
|
|
id=answer_id
|
|
)
|
|
|
|
if question.user != request.user:
|
|
|
|
return JsonResponse({
|
|
'error': 'forbidden'
|
|
}, status=403)
|
|
|
|
if answer.question != question:
|
|
|
|
return JsonResponse({
|
|
'error': 'wrong answer'
|
|
}, status=400)
|
|
|
|
question.correct_answer = answer
|
|
|
|
question.save()
|
|
|
|
return JsonResponse({
|
|
'success': True,
|
|
'correct_answer_id': answer.id
|
|
}) |