Отметка только одного ответа как принятого

Я создаю простой 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 в вашей модели вопроса и все будет в порядке!

Вернуться на верх