Отметка только одного ответа как принятого
Я создаю простой Q&A сайт, подобный Stack Overflow, и я создаю пометку ответа как принятого, но когда я реализую это, он помечает каждый ответ как принятый. То есть пользователь может принять любой ответ, но я этого не хочу. Я пытаюсь сделать так, чтобы пользователь мог отметить только один принятый ответ. И если пользователь отметил один ответ как принятый и попытался отметить второй как принятый, то первый будет удален, а второй будет отмечен
models.py
class Answer(models.Model):
answer_user = models.ForeignKey(User,on_delete=models.CASCADE)
body = models.CharField(max_length=30,null=True)
accepted = models.BooleanField(default=False)
views.py
def mark_accepted(request, question_id):
post = get_object_or_404(Answer, pk=question_id)
if request.GET.get('submit') == 'accept':
if post.accepted == True:
post.accepted = False
else:
post.accepted = True
return JsonResponse({'action':'accept'})
template.html
{% if data.accepted %}
<button name='submit' type='submit' value="like"><i class=" fas fa-correct fa-6x " ></i></button>
{% else %}
<button name='submit' type='submit' value="like"><i class=" fal fa-correct fa-6x "></i></button>
{% endif %}
<script>
$('.likeForm').submit(function (e) {
e.preventDefault();
let thisElement = $(this)
$.ajax({
url: thisElement.attr('action'),
data: {
'submit': 'accept',
},
dataType: 'json',
method: 'get',
if (response.action == 'accept') {
accept ++
$(`#id_likes${thisElement.attr('data-pk')}`).html(`<button name='submit' type='submit' value="like"><i class=" fas fa-correct fa-6x "></i></button>`)
// Followed
$(`#followed_likes${thisElement.attr('data-pk')}`).html(`<button name='submit' type='submit' value="like"><i class=" fas fa-correct fa-6x "></i></button>`)
}
</script>
Прежде всего, вашей конечной точке нужны два параметра: question_id и answer_id.
Второе, после успешного получения ответа по answer_id, вы должны сначала обновить все принятые поля на false для всех записей, где question_id=question_id и accepted=true; затем вы должны обновить принятое поле записи, где question_id=question_id и answer_id=answer_id на true.
NOTE: Модель Answer нуждается в FK (вопрос) к модели Question. И его PK является answer_id.
Вот как я бы это сделал.
Во-первых, ваша Answer
модель должна иметь отношение ForeignKey с Question
моделью.
Нравится
class Answer(models.Model):
answer_user = models.ForeignKey(User,on_delete=models.CASCADE)
body = models.CharField(max_length=30,null=True)
accepted = models.BooleanField(default=False)
question = models.ForeignKey(Question, on_delete=models.CASCADE)
Вы также должны передать ans_id
в представлении mark_as_accepted
для уникальной идентификации текущего ответа, который должен быть отмечен как принятый.
По вашему мнению,
- Запросите модель Answer и получите ранее принятый ответ (если таковой имеется). Назовите это
prev_accepted_ans
.prev_accepted_ans = Answer.objects.filter(question=question_id, accepted=True)
- Внутри условия else в вашем представлении необходимо отметить атрибут принятого ранее ответа (
prev_accepted_ans
) на False.prev_accepted_ans.update(accepted=False)
def mark_accepted(request, question_id, ans_id):
# Get the previously accepted answer (if any).
prev_accepted_ans = Answer.objects.filter(question=question_id, accepted=True)
# Get the answer that should be marked as accepted.
post = get_object_or_404(Answer, id=ans_id)
if request.GET.get('submit') == 'accept':
if post.accepted == True:
post.accepted = False
else:
# Mark the accepted attribute of prev_accepted_ans as False
prev_accepted_ans.update(accepted=False)
post.accepted = True
return JsonResponse({'action':'accept'})
Думаю, самым простым способом сделать это будет добавление поля accepted_answer в саму модель Question!
class Answer(models.Model):
answer_user = models.ForeignKey(User,on_delete=models.CASCADE)
body = models.CharField(max_length=30,null=True)
class Question(models.Model):
...
accepted_answer = models.ForeignKey(Answer, on_delete=models.SET_NULL, null=True, blank=True)
теперь вам просто нужно изменить accepted_answer в вашей модели вопроса и все будет в порядке!