Pass POST data in form with no action url Django - django

I have here a form with two buttons in it and when submitting, it doesn't pass the data on another page.
<form method="post" id="form-id">
#some form inputs here...
<a class="btn btn-success" id="yourFunction()" href="{% #url_here %}">published</a>
<a class="btn btn-secondary" href="{% #url_here %}">save as draft</a>
</form>
Does anyone know how to pass a post data in tag in Django, if the form tag has no action URL?
thanks in advance!

If you have a multiple button inside a form where this button has a different location/URL to go you can use this Javascript property to modify or set the action to the different buttons inside the form.
function yourFunction() {
document.getElementById("form-id").action = "your url";
}

Related

Django: How can I set form instance as a variable which was defined inside the HTML page?

So my blog has posts and comments.
I want the users to be able to edit the comment through a BOOTSTRAP MODAL that opens inside the same page when you click the edit button.
But I'm actually facing a problem, now there is a for loop inside the html page where I defined the comment variable :
{%for comment in comments%}
<button type="button" class="btn btn-warning btn-sm" data-toggle="modal" data-
target="#Edit{{comment.id}}Modal">edit test</button>
{%endfor%}
Code at Views.py :
post = Post.objects.get(slug=slug)
comments = post.comment_set.all()
if request.method == 'POST':
editcommentform = CommentForm(request.POST, instance=comment)
if editcommentform.is_valid():
editcommentform.save()
else:
editcommentform = CommentForm(instance=comment)
now in my views.py I cannot actually set the instance to comment because I get an error of "comment is not defined"
My question is how can i set the instance to comment while it's only defined inside the for loop in the HTML page?
Sorry if it may sound unclear or weird, I am new to the field.
You put a name for the button and use it in the view function
{%for comment in comments%}
<button type="button" class="btn btn-warning btn-sm" data-toggle="modal" data-
target="#Edit{{comment.id}}Modal" name={{comment.id}}>edit test</button>
{%endfor%}
then you can make the function takes comment_id as an argument and use it to update the db

Custom `password_reset_confirm.html` template won't redirect to `password_reset_complete` view

I made a custom password_reset_confirm.html template. But when a user enters a new password and hits submit, the browser does not redirect to the admin view password_reset_complete.
Here's the form I made in the custom password_reset_confirm.html template:
<div ng-app="app" ng-controller="Ctrl">
<form id="reset-pw-confirm-form" name="newPWForm" method="post" action="">
{% csrf_token %}
<input
id="id_new_password1"
type="[[[ newPW.showPW ? 'text' : 'password' ]]]"
name="new_password1"
ng-model="newPW.pw"
ng-minlength="8"
ng-maxlength="32"
required>
<button class="btn btn-primary" type="submit" ng-disabled="!newPW.pw">Submit</button>
<input
id="id_new_password2"
type="hidden"
value="[[[ newPW ]]]"
name="new_password2"
ng-model="newPW"
ng-minlength="8"
ng-maxlength="32"
required>
</form>
</div>
When I fill out the password and hit submit, the browser sends a POST request to the same URL it landed on, but the page seems to just refresh with nothing changed. The user's password remains unchanged. It seems Django's auth/views.py did not execute properly.
In that view, there's this code:
if post_reset_redirect is None:
post_reset_redirect = reverse('password_reset_complete')
else:
post_reset_redirect = resolve_url(post_reset_redirect)
When I have the view print post_reset_redirect, it prints None. Could this be the issue?
How can I make my custom template compatible with Django's password_reset_confirm view?
When you specifies "action" attribute for the form it will be used as your link for data sending so probably your logic isn't handled. Try to remove it and check you js files that the data is sent to the the specified link.
Also please check all required parameters for the password_reset_confirm
https://docs.djangoproject.com/en/1.8/_modules/django/contrib/auth/views/
My hidden input's value and ng-model attributes needed to be set to newPW.pw.

How to use django-markdownx in my view in similar way to admin?

I'm stuck using django-markdownx to automatically update page and to submit changes.
I followed this question and answer and managed to get django-markdownx working in admin, and within my view. However in my view editing the textarea does not automatically update the page.
The admin page with django-markdownx is exactly what I want, updating the textarea updates the page, but not the underlying database field until you hit save.
So I then tried to rip out the admin code into my own view.
In my view/template I have a form, textarea similar to admin one. I also included "/static/markdownx/js/markdownx.js" and set my form to mostly be similar to the admin page:
<form method="POST" action="">{% csrf_token %}
<div class="markdownx">
<textarea name="myfield" rows="10" cols="40" required="" data-markdownx-upload-urls-path="/markdownx/upload/" data-markdownx-editor-resizable="" class="markdownx-editor" id="id_myfield" data-markdownx-urls-path="/markdownx/markdownify/" data-markdownx-latency="500" data-markdownx-init="" style="transition: opacity 1s ease;">
{{ note.myfield }}
</textarea>
</div>
<div class="markdownx-preview">
{{ note.formatted_markdown|safe }}
</div>
</form>
This didn't work.
I see periodically there is requests to /markdownx/markdownify/ when you edit in admin, but not mine. I'm not sure if I should aim to do the same or just do some timed javascript page refresh and pass all the data from within my form back to my view to then re-render the page again.
I can't quite get my head around the django-markdownx documentation.
UPDATE:
The Documentation seems to suggest that a call to MarkdownX() should do the initialisation.
<script src="/static/markdownx/js/markdownx.js"></script>
...
<script type="text/javascript">
let parent = document.getElementsByClassName('markdownx');
let md = new MarkdownX( element, element.querySelector('.markdownx-editor'), element.querySelector('.markdownx-preview'));
</script>
But when I try this I get.
Uncaught ReferenceError: MarkdownX is not defined
Also I don't see any initialisation like this within the admin page.
Is there an example of using the django-markdownx in your own views similar to the usage within admin?
Thanks
LB
The following is a broken solution.
The correct method would be to use the MarkdownX's built-in Javascript, but I just can't get it to work, yet. So, I wrote my own. It may be of use to others.
In template html, include js.cookie.min.js in order to get the django csrftoken. Then a callback function which will be called when a change is made to the textarea. We then update the preview div with HTML code we received back from MarkdownX's markdownify call.
<script src="https://cdn.jsdelivr.net/npm/js-cookie#2/src/js.cookie.min.js"></script>
...
<script type="text/javascript">
function myMDFunc( elem ) {
input = elem.value;
var csrftoken = Cookies.get('csrftoken');
$.ajax(
{
type: "POST",
url: "/markdownx/markdownify/",
data: { CSRF: csrftoken, csrfmiddlewaretoken: csrftoken, content: input}
})
.done(function(data, status){
document.getElementById("markdownx-preview").innerHTML = data;
});
}
</script>
Still in the template html, in the form, call this function both for onchange and onkeyup.
<form method="POST" action=""> {% csrf_token %}
{{ note.title }}
<div class="markdownx">
<textarea onchange="myMDFunc(this)" onkeyup="myMDFunc(this)" cols="60" rows="5" name="text" >
{{ note.myfield }}
</textarea>
</div>
<div class="markdownx-preview" id="markdownx-preview">
{{ note.formatted_markdown|safe }}
</div>
<input type="submit" id="submit" name="submit">
</form>
In summary, a change to the textarea means we invoke the 'onchange' or 'onkeyup', which calls myMDFunc. Then myMDFunc does an ajax call with data which is the raw MarkDown code, the response to this call is the pretty HTML data. The callback within myMDFunc updates the preview with that pretty HTML.
It kinda works. I'm sure the real MarkdownX code will handle drag'n'drop of images and pacing the ajax calls to be nice to the server.

preventing hardcoded url to delete in django

I have a link and button inside it that deletes a record associated with the button
<a href="{% url 'parts:stock_delete' stock.id %}">
<button class="delete" type="submit" name="delete_btn" style="position: absolute; right: 40px;" >Delete</button>
</a>
but I want the record to be deleted only when the button is pressed but not when URL is typed in the address bar like:
http://127.0.0.1:8000/parts/stock_delete/16/
what can be done for this?
You should really use DeleteView!
It's a generic class-based view that - when viewed (GET) will display a confirmation page asking if you really want to delete the record. When you confirm (POST) the record will be deleted.
#sasuke's answer doesn't take into consideration another large security hole, CSRF. You'll want to study this page very closely if you want to ensure that your application is secure.
You can do as Kye said, use DeleteView via post to exclude the registry. There is a concern with CSRF, but Django already provides a way for AJAX requests to bring the token. You can check in the documentation:https://docs.djangoproject.com/en/1.11/ref/csrf/#setting-the-token-on-the-ajax-request
You can use post method. And when the button is pressed, you can pass some flag, say flag1.
<form action="{% url 'parts:stock_delete' stock.id %}" method="post" >
<input type="hidden" name="flag1" value="True" >{% csrf_token %}
<button class="delete" type="submit" name="delete_btn" style="position: absolute; right: 40px;" >Delete</button></a>
</form>
and in the backend you can write like this in your function in views.py.
# delete view
....
if request.method == 'POST':
if 'flag1' in request.POST:
... # deleted your object here

How to send data from django template to views method in post request or in a way data is not visible in the URL

I have a django template which has multiple <a> tags.
<a class="label label-success" href="get_status/?token={{book.token}}">Update</a>
On click of it, a method from views is called where I can access the token from the url as
tkn = request.GET.get('token')
But now I want not to send the token in the url.
I searched for this and get to know about forms but I did not clearly understand them. Can anyone please help here.
For future ref: I created a form and added a hidden input field in it.
on click of submit button it will send the token value.
<form action="get_Status/" method="post">
{% csrf_token %}
{{ form }}
<input type="hidden" name="book_token" value="{{book.token}}">
<input type="submit" class="submit_btn btn label-success" value="Update" />
</form>
Ans in the views.py
book_token=request.POST.get("book_token"," ")
You can use the basic HTML form concept here.
Please check the link:
How to submit a form with JavaScript by clicking a link?
Use javascript/Jquery to submit the form.
Insert the token value in a hidden field and use form to submit it to views.
Then in the views,you can get the value as :request.POST['token']