403 Запрещенная ошибка При редактировании формы — Javascript и Django

#javascript #django #django-models #django-views

Вопрос:

Я пытаюсь использовать форму для редактирования предыдущего поста на моем сайте. После нажатия кнопки изменить, используя Javascript, я бы хотел, чтобы это произошло без необходимости перезагрузки страницы.

Я использую Django и пытаюсь использовать fetch в файле Javascript, но я совершенно не понимаю, почему это не работает. У меня было много проблем с сохранением данных в базе данных, но в то же время я использовал Javascript. Любая помощь приветствуется.

Когда я нажимаю «Изменить» и пытаюсь сохранить, я получаю ошибку 403 «Запрещено».

уместно urls.py — Я попробовал это с помощью edit_post/, но это все равно не сработало:

 path('edit_post', views.edit_post),
 

язык JavaScript:

 edit = document.querySelectorAll(".edit");
edit.forEach((element) => {
  element.addEventListener("click", () => {
    edit_handeler(element);
  });
});

function edit_post(id, text) {
form = new FormData();

form.append("id", id);
form.append("text", text.trim());

  fetch("edit_post", {
    method: "POST",
    body: form,
  }).then((res) => {

    document.querySelector(`#post-content-${id}`).textContent = text;     
    document.querySelector(`#post-content-${id}`).style.display = "block";
    document.querySelector(`#post-edit-${id}`).style.display = "none";
    document.querySelector(`#post-edit-${id}`).value = text.trim(); 
});
}

function edit_handeler(element) {
  id = element.getAttribute("data-id");
  edit_btn = document.querySelector(`#edit-btn-${id}`);

  if (edit_btn.textContent == "Edit") {
 
    document.querySelector(`#post-content-${id}`).style.display = "none";
    document.querySelector(`#post-edit-${id}`).style.display = "block";

    edit_btn.textContent = "Save"; 
    edit_btn.setAttribute("class", "text-success edit");

      } else if (edit_btn.textContent == "Save") {
     edit_post(id, document.querySelector(`#post-edit-${id}`).value); //here

    edit_btn.textContent = "Edit";
    edit_btn.setAttribute("class", "text-primary edit");
  }
}
 

views.py

 def edit_post(request):
    if request.method == "POST":
        post_id = request.POST.get('id')
        new_post = request.POST.get('text')
        try:
            # somewhere here is not working
            post = Post.objects.get(id=post_id)
            if post.user == request.user:
                post.text = new_post.strip()
                #tried newpost.save() did not work
                post.save()
                return JsonResponse({}, status=201)
        except:
            return JsonResponse({}, status=404)

    return JsonResponse({}, status=400)
 

models.py

 class User(AbstractUser):
    pass

class Post(models.Model):
    text = models.TextField(max_length=500, blank=True, null=True)
    username = models.ForeignKey('User', on_delete=models.CASCADE, 
related_name='author', 
        null=True, blank=True)
    timestamp = models.DateTimeField(auto_now_add=True)      
    like = models.ManyToManyField(
        User,  blank=True, related_name="liked_user")

    def __str__(self):
        return self.username.username #used to be .user.username
 

Комментарии:

1. Вам нужно передать csrf_token вместе с данными формы. В противном случае вы хотите украсить представление @csrf_exempt декоратором, если считаете, что внешние приложения также могут отправлять запросы на публикацию в это представление.

Ответ №1:

Очень распространенной ошибкой является забывание о защите от подделки межсайтовых запросов, которая активна по умолчанию в Django, скорее всего, это вызывает ошибку 403, поэтому у вас есть несколько вариантов:

Вариант 1: Удалите защиту CSRF, вы можете сделать это, удалив django.middleware.csrf.CsrfViewMiddleware настройки промежуточного программного обеспечения, легко, но не рекомендуется.

Вариант 2. Еще одно простое решение-удалить защиту CSRF только для конкретного представления, например:

 from django.views.decorators.csrf import csrf_exempt

@csrf_exempt
def edit_post(request):
    ...
 

лучше, но все равно не рекомендуется.

Вариант 3: Отправьте токен CSRF для прохождения защиты, по умолчанию токен CSRF будет отображаться через файл csrftoken cookie , и запрос ajax должен отправить его в виде заголовка X-CSRFToken , например:

 function getCookie(name) {
    let cookie = {};
    document.cookie.split(';').forEach(function(el) {
        let [k,v] = el.split('=');
        cookie[k.trim()] = v;
    })
    return cookie[name];
}

const csrftoken = getCookie('csrftoken');

fetch("edit_post", {
    method: "POST",
    body: form,
    headers: {
        'X-CSRFToken': csrftoken
    },
}).then((res) => {
    ...
 

Комментарии:

1. Спасибо! Я сделал декоратор, освобожденный от csrf, а также достал программное обеспечение django.middleware.csrf.CsrfViewMiddleware из settings.py файл. Однако ошибка 403 исчезает. Но я заметил, что внесенные мной изменения не сохраняются в базе данных. Вы заметили что-нибудь не так в моем views.py досье? Я играл с ним, но не уверен, почему он не сохраняется в базе данных.

2. Я думаю , проблема в том, что у вас есть условие post.user == request.user , согласно вашим моделям, оно должно быть post.username == request.user , эта проблема скрыта из-за вашей слепой попытки…за исключением.