#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
, эта проблема скрыта из-за вашей слепой попытки…за исключением.