I'm trying to edit a form on this site with Django, and save the edits using Javascript (but not mandating a page refresh).
When the user clicks 'edit' on the page, nothing happens. No console errors. I think the issue is in the Javascript function edit_post. I'm new to using Javascript with Django. Any help is appreciated.
Relevant urls.py
path('edit_post/<str:id>', views.edit_post, name="edit_post"), #before was pk not id
path('edit_post/', views.edit_post),
path("profile/<str:username>", views.profile, name="profile"),
Javascript
function edit_handeler(element) {
id = element.getAttribute("data-id");
document.querySelector(`#post-edit-${id}`).style.display = "block";
document.querySelector(`#post-content-${id}`).style.display = "none";
// everything above this works and opens up the form for editing
edit_btn = document.querySelector(`#edit-btn-${id}`);
edit_btn.textContent = "Save";
edit_btn.setAttribute("class", "text-success edit");
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");
}}
function edit_post(id, post) {
const body = document.querySelector(`#post-content-${id}`).value;
fetch(`/edit_post/${id}`, {
method: "POST",
body: JSON.stringify({
body:body
})
}).then((res) => {
document.querySelector(`#post-content-${id}`).textContent = post;
document.querySelector(`#post-content-${id}`).style.display = "block";
document.querySelector(`#post-edit-${id}`).style.display = "none";
document.querySelector(`#post-edit-${id}`).value = post.trim();
});
}
Relevant html
<span id="post-content-{{i.id}}" class="post">{{i.text}}</span> <br>
<textarea data-id="{{i.id}}" id="post-edit-{{i.id}}"
style="display:none;" class="form-control textarea" row="3">{{i.text}}</textarea>
<button class="btn-btn primary" data-id="{{i.id}}" id="edit-btn-{{i.id}}"
onclick="edit_handeler(this)" >Edit</button> <br><br>
views.py
def edit_post(request, id):
post = Post.objects.get(id=id)
form = PostForm(instance=post)
if request.method == "POST":
form = PostForm(request.POST, instance=post)
if form.is_valid():
form.save()
return JsonResponse({}, status=201)
else:
if request.method == "GET":
form = PostForm(instance=post)
form_for_post = {'form': PostForm()}
return render(request, "network/make_post.html", {
"post": post,
"form_for_post": form,
})
Related
I want to redirect to same page after submitting form which fetches view from views.py. The problem is paginator. After submitting Django form page reloads to page 1. I want browser to stay on the same page after submitting form. Error I get: django.urls.exceptions.NoReverseMatch: 'http' is not a registered namespace. Help would be greatly appreciated!
Code calling path in js:
let path = window.location.href
Fetching api:
subedit[i].addEventListener('click', () => {
fetch(`/edit/${content[i].id}`,
{
method: 'POST',
headers: {'X-CSRFToken': csrftoken},
mode: 'same-origin',
body: JSON.stringify({
post: textarea[i].value,
page: path
})}).then(() => {
editdiv[i].style.display = 'none';
post[i].style.display = 'block';
})})
views.py:
def edit(request, post_id):
data = json.loads(request.body)
content = data.get("post", "")
post=Post.objects.get(id=post_id)
page = data.get("page", "")
if request.method == "POST":
if post.user == request.user:
post.post=content
post.save()
return HttpResponseRedirect(reverse(str(page)))
reverse(…) [Django-doc] looks for a view with the given name, it does not take a URL as input. You can use this directly in the HttpResponseRedirect [Django-doc], so:
def edit(request, post_id):
data = json.loads(request.body)
content = data.get("post", "")
post=Post.objects.get(id=post_id)
page = data.get("page", "")
if request.method == 'POST':
if post.user == request.user:
post.post=content
post.save()
return HttpResponseRedirect(page)
You should also return HttpResponses for the GET requests, and in case the post.user is not the same as the request.user.
Note: It is often better to use get_object_or_404(…) [Django-doc],
then to use .get(…) [Django-doc] directly. In case the object does not exists,
for example because the user altered the URL themselves, the get_object_or_404(…) will result in returning a HTTP 404 Not Found response, whereas using
.get(…) will result in a HTTP 500 Server Error.
Note: You can limit views to a view to authenticated users with the
#login_required decorator [Django-doc].
I was able to get it working using sessions:
<a id="page" class="page-link">{{ num }}</a>
let page=document.querySelector("#page").innerHTML
fetch(`/edit/${content[i].id}`,
{
method: 'POST',
headers: {'X-CSRFToken': csrftoken},
mode: 'same-origin',
body: JSON.stringify({
post: textarea[i].value,
page: page
})}).then(() => {
editdiv[i].style.display = 'none';
post[i].style.display = 'block';
})})
def edit(request, post_id):
data = json.loads(request.body)
content = data.get("post", "")
post=Post.objects.get(id=post_id)
page = data.get("page", "")
request.session['page'] = page
if request.method == "POST":
if post.user == request.user:
post.post=content
post.save()
return HttpResponse(page)
def index(request):
posts = Post.objects.all().order_by('-date')
paginator = Paginator(posts,10)
page_number = request.GET.get('page')
if request.session.has_key('page'):
page_number = request.session['page']
del request.session['page']
I use in my study project django rest framework.I get an error 403 Forbidden (CSRF token missing or incorrect, when I try to save using the POST method. Here is my code html
<form id = "product_form" method = "post">
{% csrf_token %}
<input type = "hidden" name = "id" id = "id">
<p>Назвние:<input name = "name" id = "name"></p>
<p><input type = "reset" value = "Oчистить"></p>
<input type = "submit" value = "Сохранить">
</form>
Here is my code js:
let productUpdater = new XMLHttpRequest();
productUpdater.addEventListener('readystatechange', () => {
if (productUpdater.readyState == 4) {
if ((productUpdater.status == 200) || (productUpdater.status == 201)) {
listLoad();
name.form.reset();
id.value = '';
} else {
window.alert(productUpdater.statusText)
}
}
}
);
name.form.addEventListener('submit', (evt) => {
evt.preventDefault();
// let vid = id.value, url, method;
let vid = id.value;
if (vid) {
url = 'http://127.0.0.1:8000/books/api_category/' + vid + '/';
method = 'PUT';
} else {
url = 'http://127.0.0.1:8000/books/api_category/';
method = 'POST';
}
let data = JSON.stringify({id: vid,nameCategory: name.value});
productUpdater.open(method, url, true);
productUpdater.setRequestHeader('Content-Type', 'application/json');
productUpdater.send(data);
})
Here is my views.py:
#api_view(['GET', 'POST'])
def api_products(request):
if request.method == 'GET':
productsAll = CategoryMaskarad.objects.all()
serializer = CategorySerializer(productsAll, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = CategorySerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
#api_view(['GET', 'PUT', 'PATCH', 'DELETE'])
def api_rubric_detail(request, pk):
product = CategoryMaskarad.objects.get(pk=pk)
if request.method == 'GET':
serializer = CategorySerializer(product)
return Response(serializer.data)
elif request.method == 'PUT' or request.method == 'PATCH':
serializer = CategorySerializer(product, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
elif request.method == 'DELETE':
product.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
Here is my urls.py:
path('api_category/<int:pk>/', api_rubric_detail),
path('api_products/', api_products),
path('api/drf-auth/', include('rest_framework.urls'))
I added the last path and logged in. In the api interface it became possible to add to the api using the post method, but with the help of js in my html I cant add data.Help me, please
I have this option. He is work.I added to js file:
name.form.addEventListener('submit', (evt) => {
evt.preventDefault();
// let vid = id.value, url, method;
let vid = id.value, url, method;
if (vid) {
url = 'http://127.0.0.1:8000/books/api_category/' + vid + '/';
method = 'PUT';
} else {
url = 'http://127.0.0.1:8000/books/api_category/';
method = 'POST';
}
let data = JSON.stringify({id: vid, nameCategory: name.value});
productUpdater.open(method, url, true);
productUpdater.setRequestHeader('Content-Type', 'application/json');
productUpdater.setRequestHeader('X-CSRFToken', csrftoken);
productUpdater.send(data);
})
and I added to html file:
<script>
const csrftoken = document.querySelector('[name=csrfmiddlewaretoken]').value;
</script>
when passing data in form to a django rest framework, you do not add the csrf_token tag before forms, rather you pass it as a header when sending api post on your endpoint.
Add this line after
try adding this function into your codes to get the values of csrftoken
let getCookie = (name)=>{
var cookieValue = null;
if(document.cookie && document.cookie !== ''){
var cookies = document.cookie.split(";");
for(var i=0; i<cookies.length; i++){
var cookie = cookies[i].trim();
if(cookie.substring(0, name.length+1)===(name+'=')){
cookieValue = decodeURIComponent(cookie.substring(name.length+1));
break;
}
}
}
return cookieValue;
}
and then change the value you use in x-csrf-token and make it
productUpdater.setRequestHeader('Content-Type', 'application/json');
productUpdater.setRequestHeader('X-CSRF-Token', getCookie("csrftoken"));
I'm trying to edit an existing form on my site, and save the edits using Javascript (without requiring a refresh of the page). I'm using Django as well.
So far, when the user clicks 'edit' on the page, the form appropriately appears, showing the information already saved there. But when I click 'save' I get a 404 error.
The issue is in the Javascript function edit_post. I'm not sure if I have used stringify correctly either, I'm new to using Javascript with Django. Any help is appreciated.
function edit_handeler(element) {
id = element.getAttribute("data-id");
document.querySelector(`#post-edit-${id}`).style.display = "block";
document.querySelector(`#post-content-${id}`).style.display = "none";
// everything above this works and opens up the form for editing
edit_btn = document.querySelector(`#edit-btn-${id}`);
edit_btn.textContent = "Save";
edit_btn.setAttribute("class", "text-success edit");
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");
}}
function edit_post(id, post) {
const body = document.querySelector(`#post-content-${id}`).value;
fetch("/edit_post/", {
method: "POST",
body: JSON.stringify({
body:body
})
}).then((res) => {
document.querySelector(`#post-content-${id}`).textContent = post;
document.querySelector(`#post-content-${id}`).style.display = "block";
document.querySelector(`#post-edit-${id}`).style.display = "none";
document.querySelector(`#post-edit-${id}`).value = post.trim();
});
}
Relevant html - this is inside a card, for the post itself in the html file:
<span id="post-content-{{i.id}}" class="post">{{i.text}}</span> <br>
<textarea data-id="{{i.id}}" id="post-edit-{{i.id}}"
style="display:none;" class="form-control textarea" row="3">{{i.text}}</textarea>
<button class="btn-btn primary" data-id="{{i.id}}" id="edit-btn-{{i.id}}"
onclick="edit_handeler(this)" >Edit</button> <br><br>
views.py
def edit_post(request, pk):
post = Post.objects.get(id=pk)
form = PostForm(instance=post)
if request.method == "POST":
form = PostForm(request.POST, instance=post)
if form.is_valid():
form.save()
return JsonResponse({}, status=201) # this works to edit and save to db
else:
if request.method == "GET":
form = PostForm(instance=post)
form_for_post = {'form': PostForm()}
return render(request, "network/make_post.html", {
"post": post,
"form_for_post": form,
})
urls.py (relevant ones)
path('edit_post/<str:pk>/', views.edit_post, name="edit_post"),
path('edit_post/', views.edit_post),
path("profile/<str:username>", views.profile, name="profile"),
Assuming you're running your django server locally and you're getting a 404 returned from your fetch request, then that means the url path does not exist. Either your django server isn't live or the url you're supplying the fetch request with is incorrect. If /edit_post/ is your desired endpoint, try fetching with the servers full request URL
Something like this
http://localhost:8000/edit_post
Replace 8000 with whatever port your server is running at.
Your fetch body is structured properly btw.
This question already exists:
Problem with the form return empty data in Flask [duplicate]
Closed 1 year ago.
I am building an application in Flask and JavaScript and I have a problem with the Ajax in Flask. How can I handle it in Flask i mean using if. I use if request.method=='POST' but I have the form too and when I try if 'form-submit' in request.form and print nazwa_event = request.form.get('nameOfEvent') this return me nothing I mean it is empty.
Code JavaScript:
$("#search-button_event").click(function () { // make ajax request on btn click
$.ajax({
type: "POST",
url: "/mapaa", // url to the function
data: {
nameevent: $("#name_of_event").val(), // value of the form
},
success: function (response) {
id = (response['id']);
nazwa = (response['name']);
droga = (response['route']);
droga_without = droga.replaceAll("{","")
droga_with2 = droga_without.replaceAll("}","")
var string = droga_with2.split(',');
let marker_event = L.marker(array[0]).bindPopup()
marker_event._popup.setContent(
'<form method="POST" action="/mapaa"'+
'<p>Nazwa: '+nazwa+'</p>'+
'<input name="nameOfEvent" type="hidden" value="" id="idname">'+
'<button type="submit" id="form-submit" name="form-submit" class="btn btn-warning btn-block">Dołącz do wydarzenia</button>'+
'</form>')
marker_event.addTo(mymap)
polyline_event = L.polyline(array,{color: 'red'})
marker_event.on('click',function(){
polyline_event.addTo(mymap)
})
marker_event.getPopup().on('remove', function() {
polyline_event.remove()
})
$('input[id=idname]').val(nazwa.value);
mymap.setView(array[0],14)
},
});
});
Code in Flask:
#app.route('/mapaa',methods=['GET','POST'])
def mapa():
user_id = current_user.get_id()
slownik = {}
if request.method == "POST":
if request.is_json:
req = request.get_json()
nazwa = req['name']
data_pocz = req['data_start']
data_kon = req['data_end']
typ = req['type']
dlugosc = req['len_route']
coord = req['coordinates']
event_database = Event(date_start=data_pocz, date_end=data_kon, type=typ, name=nazwa, len_route=dlugosc,admin=user_id, route=coord)
db.session.add(event_database)
db.session.commit()
print('Dodano wydarzenie')
if 'form-submit' in request.form:
nazwa_event = request.form.get('nameOfEvent')
print("Name:",nazwa_event)
else:
name_ev = request.form.get('nameevent')
all_data = Event.query.filter_by(name=name_ev).all()
for row in all_data:
date_st_string = str(row.date_start)
date_end_string = str(row.date_end)
slownik = {'id':row.id,'date_st':date_st_string,'date_end':date_end_string,'type':row.type,'name':row.name,'len_route':row.len_route,'route':row.route}
return jsonify(slownik)
return render_template('mapaa.html', title='Mapa')
It is problem with the form or name of something ?
I am trying to submit a form using ajax to django view but without jquery, and i am not able to get through few things.
I am unable to send formData to django via ajax
Also unable to check if the request is made via ajax or not (request.is_ajax())
I am using core Javascript for this functionality so any help will be appreciated.
Views.py
def register(request):
if request.method == "POST":
form = RegisterForm(request.POST)
if form.is_valid():
if request.is_ajax():
# form is submited via ajax
else:
# error submitting the form via ajax
else:
return JsonResponse({'error':'There was an error'})
else:
form = RegisterForm()
context = {
'form' : form
}
return render(request, 'users/register.html', context)
AJAX
function _(e){
return document.getElementById(e);
};
function getCookie(name){
var cookieValue = null;
if(document.cookie){
var cookies = document.cookie.split(';');
for(var i = 0; i < cookies.length; i++){
cookie = cookies[i].trim();
if(cookie.substring(0, name.length + 1) == (name + '=')){
cookieValue = decodeURIComponent(cookie.substring(name.length+1));
break;
};
};
};
return cookieValue;
};
var btn = _('formBtn');
btn.addEventListener('click', function(e){
e.preventDefault();
var ajax = new XMLHttpRequest();
var fname = _('id_first_name').value;
var lname = _('id_last_name').value;
var email = _('id_email').value;
var password = _('id_password').value;
var csrfCookie = getCookie('csrftoken');
// formData not working
ajax.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
console.log(this.responseText);
}
};
ajax.open('POST', '/users/registerAjax/', true);
ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
ajax.setRequestHeader("X-CSRFToken", csrfCookie);
ajax.send(encodeURI('first_name='+fname+'&last_name='+lname+'&email='+email+'&password='+password));
})