hw3-5
hw3 - Введены типы данных в models.py, сайт переписан под django модели - DB переведена на PostgreSQL - Переписан docker compose файл, настроены network и volume - Добавлена команда генерации рандомных данных в db hw4 - Добавлены формы login, signup, logout, profile - Добавлены вопросы и ответы и их модели и формы hw5 - Добавлена загрузка и отображение аватарок - Добавлены лайки и дизайки, отметка правильного ответа
This commit is contained in:
1 parent
33379408ba
commit
466555ce05
26 files changed
+1722
-178
No files matched your search
+408
-34
@@ -1,49 +1,423 @@
|
||||
from django.shortcuts import render
|
||||
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
|
||||
)
|
||||
|
||||
QUESTIONS = [
|
||||
{
|
||||
"id": i,
|
||||
"title": f'Question number {i}',
|
||||
"text": f'Some text {i}',
|
||||
"tags": ["python"],
|
||||
}
|
||||
for i in range(10)
|
||||
]
|
||||
from .forms import (
|
||||
LoginForm,
|
||||
SignupForm,
|
||||
ProfileForm,
|
||||
AskForm,
|
||||
AnswerForm
|
||||
)
|
||||
|
||||
HOT_QUESTIONS = QUESTIONS[:4]
|
||||
|
||||
TAGS = {tag for q in QUESTIONS for tag in q["tags"]}
|
||||
|
||||
def index(request):
|
||||
tag = request.GET.get('tag', '')
|
||||
try:
|
||||
page_number = int(request.GET.get('page', 1))
|
||||
except ValueError:
|
||||
page_number = 1
|
||||
page = Paginator(QUESTIONS if tag == ''
|
||||
else [ cur_question for cur_question in QUESTIONS if tag in cur_question['tags']], 4)
|
||||
page_obj = page.page(page_number)
|
||||
|
||||
return render(request, 'core/index.html', context={'questions': page_obj.object_list,
|
||||
'hot_questions': HOT_QUESTIONS, 'page_obj': page_obj, 'tags': TAGS,
|
||||
'tag': tag})
|
||||
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 ask(request):
|
||||
return render(request, 'core/ask.html', context={'questions': QUESTIONS, 'tags': TAGS})
|
||||
def hot(request):
|
||||
return render(request, 'core/hot.html', context={'questions': QUESTIONS, 'tags': TAGS,
|
||||
'hot_questions': HOT_QUESTIONS,})
|
||||
|
||||
def login(request):
|
||||
return render(request, 'core/login.html', context={'questions': QUESTIONS, 'tags': TAGS})
|
||||
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 profile(request):
|
||||
return render(request, 'core/profile.html', context={'questions': QUESTIONS, 'tags': TAGS})
|
||||
|
||||
def question(request):
|
||||
return render(request, 'core/question.html', context={'questions': QUESTIONS, 'tags': TAGS})
|
||||
|
||||
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):
|
||||
return render(request, 'core/signup.html', context={'questions': QUESTIONS, 'tags': TAGS})
|
||||
|
||||
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
|
||||
})
|
||||
Reference in new issue
Block a user