I'm using Django and I want my users to confirm that they really want something to be deleted. I'm considering pure Django solution (no Javascript confirmations).
According to what I think,I can create a new page containing "Yes" and "No" buttons. If user presses "Yes", my site will go on and delete the object from the database.
Is it the right way to do deletion without using Javascript? How would you implement the feature if you were me?
I would use Django's built in DeleteView, which will display a confirmation page for an HTTP GET request and perform deletion for an HTTP POST request.
The documentation gives this example:
from django.views.generic.edit import DeleteView
from django.core.urlresolvers import reverse_lazy
from myapp.models import Author
class AuthorDelete(DeleteView):
model = Author
success_url = reverse_lazy('author-list')
I'd recommend reading the documentation for the SingleObjectMixin which explains how to customise the way the view finds the object to delete (the default is to look for an URL keyword argument called pk), and for the TemplateResponseMixin which explains how to customise the template that is used (the default is 'myapp/author_check_delete.html').
This is just one of a number of class-based generic views that make basic operations (displaying a page for a single model instance, for a list of model instances, and handling editing, deletion etc.) very quick and easy to implement.
If you wanted to enhance this with JavaScript later you could always write some unobtrusive JS that detects links to the deletion confirmation page (by looking for a class, or a particular URL) and adds a click handler that pops up a confirmation dialog and then sends a POST request to the URL in the link's href attribute. You would also need to modify the view slightly to return a JSON object when request.is_ajax() is True, so that your JS would know if the deletion had succeeded or failed, which would probably involve overriding one of the methods inherited from the DeletionMixin.
That sounds fine. What I have done a couple of times is to create a confirmation template that can be used anywhere in the application:
{% extends 'base.html' %}
{% block content %}
<div class="confirmation-box">
<p>{{ message }}</p>
<div>
Cancel
<form action="{{ action_link }}" method="post">
<input type="hidden" name="next" value="{{ prev_link }}" />
<input type="submit" value="Send" />
</form>
</div>
</div>
{% endblock %}
You pass to it:
A confirmation message for the user (message)
The url to the page you are in (prev_link)
The url that should be called to perform the action (action_link)
If the user cancels the action, then she/he goes back to the original page.
If the user confirms, then the prev_link is passed as a hidden parameter, so the view can redirect the user to the original page after performing the action (although this is completely optional of course).
Which is pretty much what you propossed in your question.
Related
I am using Flask and wtforms to create a web page "index.html" that loads multiple forms. The selection of forms that are rendered depend on dropdown selections, and a variable "serviceid" updated from an API call. The form selection and rendering is handled in an included file "form_select.html", which requires "serviceid" value to pick the correct form. I am having trouble figuring out how to refresh the forms based on updated serviceid values without doing a full page reload.
I can use something like this with jinja2 include to render "form_select.html" and pass the "serviceid" variable so the right form is rendered:
<div id="loadform"> {% include './form_select.html' with serviceid %} </div>
This is working on first load, but I need to select a new form when the user selects a new value from a dropdown. I am running a script based on mydropdown.onchange, which first obtains the correct "serviceid" value, but now I need to rerender just the loadform div with this value.
I have tried approaches along the lines of the following - but I cant seem to figure out how to deliver this jinja2 with .innerHTML.
document.getElementById('loadform').innerHTML = `
{% with serviceid=serviceid %}
{% include './form_blocks.html' %}
{% endwith %}
`;
There is probably a better way to do this, but the examples I can find don't include passing in a variable. Can I use innerHTML for this, or is there a better way?
I make my E-Commerce Website using Django. When I use Add to Cart functionality on the website refresh the page & I go to the top of the page. But I want the user to stay on the same Product after Add to Cart.
Add To Cart function is made using Session in Django, not JS.
So I want when users use Add To Cart Function user stay on the same product.
I think this thing is possible using JS.
This is Add to Cart button
<form action="{% url 'cart:AddCart' %}" method="POST">{% csrf_token %}
<input hidden type="text" name="product" value="{{i.id}}">
<button id="clickMe" class="main-btn cart cart-btn" style="padding: 5px 32px">Add <i class="fa-solid fa-cart-shopping"></i></button>
</form>
user reverse function
and in the function that handles the AddCart it should be something like this
in views.py
def addcart(request,id):
if request.method == "POST":
//handle the request and store it to the database
return HttpResponseRedirect(reverse("addcart", args=(id,)))
and the url.py should look something like this
path("addtocat/<int:id>", views.listing, name="addcart"),
other way is checking if the request is POST or GET , if it's get you should render the template page normally if it's POST use the reverse function
hope that help
I am using a javascript to send an html form to django.
js looks like this:
document.getElementById("fooform").submit();
and the html form looks like this:
<form class="form-inline" id="fooform" action ="{% url 'foo:doo' %}" method="post">
{% csrf_token %}
<input type="hidden" id="fooinput" value="" />
</form>
the js can write the data into the input field without any problems and also carry out the submit. my problem is using the crsf token.
I have already put the token {% csrf_token %} in every conceivable place. (Before the form, before the js...). in the html code is the token also correct.
django gives me the error:
Reason given for failure:
CSRF token missing or incorrect.
In general, this can occur when there is a genuine Cross Site Request Forgery, or when Django's CSRF mechanism has not been used correctly. For POST forms, you need to ensure:
Your browser is accepting cookies.
The view function passes a request to the template's render method.
In the template, there is a {% csrf_token %} template tag inside each POST form that targets an internal URL.
If you are not using CsrfViewMiddleware, then you must use csrf_protect on any views that use the csrf_token template tag, as well as those that accept the POST data.
The form has a valid CSRF token. After logging in in another browser tab or hitting the back button after a login, you may need to reload the page with the form, because the token is rotated after a login.
You're seeing the help section of this page because you have DEBUG = True in your Django settings file. Change that to False, and only the initial error message will be displayed.
You can customize this page using the CSRF_FAILURE_VIEW setting.
Edit:
The view.py:
def foo_view(request):
print(request.POST)
urls.py:
app_name = 'foo'
urlpatterns = \
[
path('doo', views.foo_view, name='foo_view'),
]
Use case (Django Project):
I want to log in on my login page -> Therefore I use this form in html (login.html):
<form class="loginform" action="" method="POST">
{% csrf_token %}
<div class="loginform">
{{form.as_p}}
</div>
<br>
<input type="submit" class="btn btn-success loginbtn" value="Login">
</form>
In case of successful log in I will redirect with DJANGO to this URL (localhost/welcome/)-> welcome.html:
LOGIN_REDIRECT_URL = "welcome"
I am able to send javascript notifications with alertify, but only when using simple things such as
click on it or mouseover:
function notification(text) {
console.log(text)
alertify.success(text);
}
I tried it with onsubmit="javascript:notification("")" in the html form tag, however this will
be displayed only BEFORE the URL redirection.
So my question is:
How is it possible to activate /send the push notification AFTER the URL redirection and in
case of successfull POST/ Log in?
I really appreciate your help! Thank you a lot!!
Javascript is client-side. That means your alertify.success(text); will be executed client-side, once server already did his render process.
The authentication process is server-side. So you have to make your server make your alertify a part of the rendered content.
Knowing that, you just have to change your LOGIN_REDIRECT_URL content page to include in it a call to notification:
<!-- your html template comes here -->
<script type="text/javascript">
notification('You are now logged in');
</script>
Be remembered that the notification will then display each time the person visits this page. You may want either to redirect him again, or to introduce a variable in Django to avoid displaying it again.
I'm doing project using Django and now I am trying to adapt js into the project. I'm not familiar with js and I'm wondering how I can manipulate db using js. For example, I want to use js for creating delete function. Currently, when I push delete button, I jump into the other page and then I have to push delete button again. But what I want to do is push the delete button and then pop up the window to confirm and delete something. How can I adapt js into Django in general?
Here is current way
first I have to push the button and jump into another page
<button style="display: inline;" onclick="window.location='{% url 'blog:delete_entry' entry_id=entry.id %}'" class="btn btn-link">Delete</button>
and then I have to push a button on the other page again.
<button type="submit" class="btn btn-outline-danger" id="delete-button">Delete</button>
Here is views.py
def delete_entry(request, entry_id):
entry = Entry.objects.get(id=entry_id)
if request.method != 'POST':
form = EditEntryForm(instance=entry)
else:
form = EditEntryForm(instance=entry)
entry.delete()
return HttpResponseRedirect(reverse_lazy ('blog:my_entry'))
return render(request, 'blog/delete_entry.html', {'entry': entry, 'form': form})
Anyone who can give me tips?
I could be wrong, but I typically only use javascript for the front-end. You are doing the back-end in Python with the Django frame work... it would be foolish not to use Python to manipulate the DB. Here is a template for mysql although I used Flask...
https://github.com/rootVIII/flask_mysql_template/blob/master/template.py
Even though it's Flask and not Django, the idea is still the same.
Your button should (or any form button) should have a Django endpoint associated with it (basically a path to the Django function). That way when the button is pressed, the Django/Python code on the back-end is ran. There you can perform your logic and database business in the Python code on the back-end.
Sorry for the Flask examples... but here is an endpoint for Flask in the index.html file from the above link... notice how the form action is associated with an endpoint /login_register
/login_register is what is ran when the form input button is pressed. It is a function on the back-end... in your case it might be named delete_entry
<form action = /login_register method="POST" id="userform">
<fieldset>
<!-- some labels and input values here -->
<input type="submit" name="submit" value="login/register" id="submit"/><br>
</fieldset>
</form>
So basically what I'm saying is that your button should not call Javascript. It should call a Python function on the back-end. And no you do not need to make a whole rest API to do this as was mentioned above