Get an object id from HTML in in request.POST - django

I have an user with list of tasks that he can add. I want to give him ability to delete those tasks, or mark as done.
The problem is that my solution is working only when user has one task, because of non-unique id's problem
Is there any way to pass the id to html so that it will be easily accesible in views? Thank you!
This is my current code
{% for task in tasks %}
<form id='is_checked' method='POST' action="{% url 'mark_as_done'%}" enctype="multipart/form-data">
{% csrf_token %}
<div class="input-group-text">
<input type="hidden" id="id_checked" value="{{task.id}}" name = "id_checked">
</div>
</form>
<form class="input-group" action="{% url 'delete_task'%}" method='POST' enctype="multipart/form-data">
{% csrf_token %}
<div class="input-group-prepend">
<div class="input-group-text">
<input onChange="document.getElementById('is_checked').submit()" type="checkbox" {% if task.is_done %}checked{% endif %}>
</div>
</div>
<h7 type="text" class="form-control">{{task}}</h7>
<input type="hidden" id="id" value="{{task.id}}" name = "id">
<button type="submit" class="input-group-append btn btn-danger">Delete</button>
</form>
{% endfor %}
And in views:
def delete_task(request):
if request.method == 'POST':
task = Task.objects.get(pk=request.POST['id'])
task.delete()
return redirect('tasks')
#login_required()
def mark_as_done(request):
if request.method == 'POST':
task = Task.objects.get(pk=request.POST['id_checked'])
task.is_done = True
task.save()
return redirect('tasks')```

Related

if request.method == "POST": the pointer is not coming in the if statement can anybody tell?

This code is not working well for the post request in the views file so anybody please try to tell me why the cursor is not going inside the "POST" please find out the problem.
views.py
#login_required()
def candidate_view(request):
if request.method == "POST":
can = candidate.objects.filter(position = 'President')
return render(request,'poll/candidate.html',{'can':can})
else:
return render(request, 'poll/candidate.html')
candidate.html
{% extends 'base.html' %}
{% block title %}Candidates{% endblock %}
{%block body%}
<h2>Available Candidates of {{ obj.title }}</h2>
<form action="" method="POST">
{% csrf_token %}
{% for c in can.candidate_set.all %}
<!-- <input type="radio" name="{{ c.position}}" value="{{c.id}}" required> <strong>{{c.name}} Detail</strong>
<br> -->
<div class="custom-control custom-radio">
<input type="radio" id="id_{{c.id}}" name="{{ c.full_name}}" value="{{c.id}}" class="custom-control-input" required>
<label class="custom-control-label" for="id_{{c.id}}">{{c.full_name}}</label>
</div>
{% empty %}
<p>No Candidates Available</p>
{% endfor %}
<br><input type="submit" class="btn btn-outline-success btn-sm" value="VOTE">
</form>
<br><p>Back to Poll</p>
{% endblock %}
vote.html
{% extends 'base.html' %}
{% block title %}Positions{% endblock %}
{%block body%}
<form action="" method="POST">
{%csrf_token%}
<ul>
<li><h2> President</h2></li>
<li><h2> Vice President </h2></li>
<li><h2> Secratary </h2></li>
<li><h2> Vice Secratary </h2></li>
</ul>
</form>
{% endblock %}
urls.py
from django.contrib import admin
from django.urls import path,include
from . import views
urlpatterns = [
path('',views.home,name="home"),
path('register',views.register,name="register"),
path('login',views.view_login,name="view_login"),
path('logout',views.view_logout,name="view_logout"),
path('candidate_view',views.candidate_view,name="candidate_view"),
path('vote',views.vote,name="vote"),
path('result',views.result,name="result"),
]
Replace
<form action="" method="POST">
{%csrf_token%}
<ul>
<li><h2> President</h2></li>
<li><h2> Vice President </h2></li>
<li><h2> Secratary </h2></li>
<li><h2> Vice Secratary </h2></li>
</ul>
</form>
with
<form action="{% url 'candidate_view' %}" method="POST">
{%csrf_token%}
<label for="President">President</label>
<input type="radio" id="President" name="position" value="President" />
<label for="Vice-President">Vice President</label>
<input type="radio" id="Vice-President" name="position" value="Vice President" />
( similarly for secretary and vice secretary )
<button>Submit</button>
</form>
Also update view.py with
def candidate_view(request):
if request.method == "POST":
can = candidate.objects.filter(position = request.POST.get("position"))
return render(request,'poll/candidate.html',{'can':can})
else:
return render(request, 'poll/vote.html')

pass data to form filed in django templae

How can I pass data to form fields in django templat ? , for example I have below code in my project:
<td class="col-3">
{{form.number|as_crispy_field}}
</td>
Can I use
<td class="col-3">
{{form.number}} = 10
</td>
in django template ?
#mosi -
<td class="col-3">
{{form.number}} = 10
</td>
No, you cannot use this. If you are planning to pass data from views to template then do something like this
Let's say you have a form something like this
forms.py
from django import forms
class ContactForm(forms.Form):
name = forms.CharField(max_length=30)
email = forms.EmailField(max_length=254)
views.py
def home(request):
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
pass # your logic here
else:
form = ContactForm()
return render(request, 'home.html', {'form': form})
template.html
<form method="post" novalidate>
{% csrf_token %}
{{ form.name }}
{{form.email}}
<button type="submit">Submit</button>
</form>
OR
Simply
<form method="post" novalidate>
{% csrf_token %}
{{ form }}
<button type="submit">Submit</button>
</form>
Now, if you want to set initial values to your form in template
Lets say you have the following
class ContactForm(forms.Form):
name = forms.CharField(max_length=30,initial='test')
Then in your template you do something like this
<form method="post" novalidate>
{% csrf_token %}
<input type="text" name="name" id="name" value="{{ form.name.value }}">
<button type="submit">Submit</button>
</form>
Now, in case of an UpdateView where data is pulled in dynamically from the Database based on let's say product id. The following is just an example
class ProductForm(forms.ModelForm):
class Meta:
model = Product
exclude = (
"created_by",
"slug",
)
class ProductUpdateView(UpdateView):
# specify the model you want to use
model = Product
form_class = ProductForm
template_name = "catalog/product/update_product.html"
product_update.html
<form method="post" enctype="multipart/form-data">
<div class="card-body">
{% csrf_token %}
{{ form.as_p}}
<button type="submit" class="btn btn-primary">Update</button>
</div>
</form>
Or
<form method="post" enctype="multipart/form-data">
<div class="card-body">
{% csrf_token %}
<input type="text" name="name" id="name" value="{{ form.name.value }}">
<input type="text" name="description" id="description" value="{{ form.description.value }}">
.........
<button type="submit" class="btn btn-primary">Update</button>
</div>
</form>

My django form is not working when i iterate through it using for loop

Basically if I tried to use this code
{% for field in form %}
<div class="input">
<label for="" class="labelinput">{{field.label}}</label>
{{field}}
</div>
{% endfor %}
the form data wont make it pass is_valid().But it renders out the form fine. and if I use this code
<form action="" method="post"> {% csrf_token %}
{{form}}
<input type="submit" value="">
it worked perfectly fine. How do I get the first code to work because I want to add classes between the label and the input field
and here's my view
def booklist_view(request):
bkff = BookListForm()
if request.method == 'POST':
bkff = BookListForm(request.POST)
if bkff.is_valid():
bkff.save()
bkff = BookListForm()
context = {
'form': bkff,
}
return render(request, 'booklist1st/booklist.html', context)
Please try this.
views.py
def booklist_view(request):
form = BookListForm(request.POST or None)
if request.method == 'POST':
if form.is_valid():
form.save()
context = {'form': form }
return render(request, 'booklist1st/booklist.html', context)
Here we render field according according to field type(hidden_fields,visible_fields).
html template:
<form method="post">
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in form.visible_fields %}
<div class="input">
{{field.label}}
{{field}}
</div>
{% endif %}
<input class="btn btn-primary" type="submit" name="add_book" value="Save and add book" />
</form>
You need to specify each field relate data like for=, id=, etc. To have maximum control over how your form is rendered, specify each field and control its style, for example, as we can't see your Form definition, this is an example on how it would be for a title field:
<form method="post">{% csrf_token %}
{# Include the hidden fields #}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{# Include the visible fields #}
{{ form.non_field_errors }}
{{ form.title.errors }}
<label for="{{ form.title.id_for_label }}">Title</label>
{{ form.title }}
{% if form.title.help_text %}
<small id="titleHelp">{{ form.title.help_text|safe }}</small>
{% endif %}
</div>
<input class="btn btn-primary" type="submit" name="add_book" value="Save and add book" />
</form>
<form method="post">
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in form.visible_fields %}
<div class="input">
<label for="" class="label">{{field.label}}</label>
{{field}}
</div>
{% endfor %}
<input class="btn btn-primary" type="submit" name="add_book" value="Save and add book" />
</form>
View.py
from django.views.decorators.csrf import csrf_protect
#csrf_protect
def booklist_view(request):
bkff = BookListForm()
if request.method == 'POST':
bkff = BookListForm(request.POST)
if bkff.is_valid():
bkff.save()
context = {
'form': bkff,
}
return render(request, 'booklist1st/booklist.html', context)

django multi form and file field

I am currently using several differences forms on a single view. I am able to fill my forms but when I submit one of them, it seems that my form is invalid. I displayed the request.POST (it contains all my information) and my form (it contains my information except files parts.)
Could you explain me how to correct it?
Could it be linked to my models?
(I am using bootstrap 3 through django)
my view :
def view_addfiles(request):
try:
print(request.POST)
except:
{}
if request.method == 'POST' and 'search' in request.POST:
print("recherche")
recherche=searchbar(request.POST, prefix='search')
if recherche.is_valid():
print("recherche")
else :
recherche=searchbar(prefix='search')
if request.method == 'POST' and 'film' in request.POST:
print("film")
addfilm=Addfilms(request.POST,request.FILES, prefix='film')
print(addfilm)
if addfilm.is_valid():
print("film")
return redirect(view_accueil, inscription=3)
else :
print("dfsd")
addfilm=Addfilms(prefix='film')
if request.method == 'POST' and 'serie' in request.POST:
print("serie")
addserie=Addseries(request.POST,request.FILES, prefix='serie')
if addserie.is_valid():
print("serie")
return redirect(view_accueil, inscription=3)
else :
addserie=Addseries(prefix='serie')
return render(request, 'menuAjout.html',locals())
my html :
<form action="{% url "add_files" %}" method="post">
{% csrf_token %}
{{ recherche.as_p }}
<input type="submit" id="validation" name="search"/>
</form>
<div id="films">
{% load bootstrap3 %}
{% bootstrap_css %}
<form action="{% url "add_files" %}" method="post">
{% csrf_token %}
{% bootstrap_form addfilm %}
{% buttons %}
<button type="submit" class="btn btn-primary" id="submitbutton" name="film" value="submit">
{% bootstrap_icon "star" %} Ajouter
</button>
{% endbuttons %}
</form>
</div>
<div id="series">
<form action="{% url "add_files" %}" method="post">
{% csrf_token %}
{% bootstrap_form addserie %}
{% buttons %}
<button type="submit" class="btn btn-primary" id="submitbutton" name="serie">
{% bootstrap_icon "star" %} Ajouter
</button>
{% endbuttons %}
</form>
</div>
my forms :
class Addseries(forms.ModelForm):
class Meta:
model = series
exclude = ('nbTelechargement','datedepot')
class Addfilms(forms.ModelForm):
class Meta:
model = series
exclude = ('nbTelechargement','datedepot')
class searchbar(forms.Form):
motclef=forms.CharField(max_length=15,widget=forms.TextInput(attrs={'placeholder': 'Search...','style':'background :#ededef url("/static/image/search.png") no-repeat;background-size: auto 90%;'}))
categorie=forms.ChoiceField(choices=(('films', 'films'),
('séries', 'séries'),
('jeux', 'jeux'),
('logiciels', 'logiciels'),
('livres', 'livres'),
('musiques', 'musiques')))
I see several things:
It's not a Django issue but a HTML one:
When a user submits a form, he/she submits only form.
Django receives in request.POST only the data sent by one form.
Your forms share the same fields' names.
Addseries.nbTelechargement and Addfilms.nbTelechargement will have the same key in request.POST
I just forgot to add enctype="multipart/form-data" in my form balise.
My request.FILES was empty because of that.
So my form was unvalid because of that.

Django Admin Action Confirmation Page

In my Django project I have an admin action which requires an confirmation page. I oriented it on the delete_selected action, but it does not work. Here is what I have.
part of my admin.py
def my_action(modeladmin, request, queryset):
if request.POST.get('post'):
print "Performing action"
# action code here
return None
else:
return TemplateResponse(request, "admin/my_action_confirmation.html")
admin/my_action_confirmation.html
<form action="" method="post">{% csrf_token %}
<div>
<input type="hidden" name="post" value="yes" />
<input type="hidden" name="action" value="my_action" />
<input type="submit" value="Confirm" />
</div>
</form>
This works almost. I get to the confirmation page but if I click "confirm" I just get back to the original page. The part with the action code is never reached. In fact the my_action function isn't called a second time. So how do I tell django, that the my_action function should be called a second time, once I clicked confirm?
Edit: I was more missing then I thought
The corrected my_action
def my_action(modeladmin, request, queryset):
if request.POST.get('post'):
print "Performing action"
# action code here
return None
else:
request.current_app = modeladmin.admin_site.name
return TemplateResponse(request, "admin/my_action_confirmation.html")
admin/my_action_confirmation.html
{% load l10n %}
<form action="" method="post">{% csrf_token %}
<div>
{% for obj in queryset %}
<input type="hidden" name="{{ action_checkbox_name }}" value="{{ obj.pk|unlocalize }}" />
{% endfor %}
<input type="hidden" name="post" value="yes" />
<input type="hidden" name="action" value="my_action" />
<input type="submit" value="Confirm" />
</div>
</form>
admin.py
def require_confirmation(func):
def wrapper(modeladmin, request, queryset):
if request.POST.get("confirmation") is None:
request.current_app = modeladmin.admin_site.name
context = {"action": request.POST["action"], "queryset": queryset}
return TemplateResponse(request, "admin/action_confirmation.html", context)
return func(modeladmin, request, queryset)
wrapper.__name__ = func.__name__
return wrapper
#require_confirmation
def do_dangerous_action(modeladmin, request, queryset):
return 42/0
admin/action_confirmation.html
{% extends "admin/base_site.html" %}
{% load i18n l10n admin_urls %}
{% block bodyclass %}{{ block.super }} app-{{ opts.app_label }} model-{{ opts.model_name }} delete-confirmation
delete-selected-confirmation{% endblock %}
{% block content %}
<p>Are you sure you want to {{ action }}?</p>
<ul style="padding: 0">
{% for object in queryset.all %}
<li style="list-style: none; float: left; margin: 5px">
{{ object }}
</li>
{% endfor %}
</ul>
<hr>
<br>
<form action="" method="post">{% csrf_token %}
<fieldset class="module aligned">
{% for obj in queryset.all %}
<input type="hidden" name="_selected_action" value="{{ obj.pk|unlocalize }}"/>
{% endfor %}
</fieldset>
<div class="submit-row">
<input type="hidden" name="action" value="{{ action }}"/>
<input type="submit" name="confirmation" value="Confirm"/>
<a href="#" onclick="window.history.back(); return false;"
class="button cancel-link">{% trans "No, take me back" %}</a>
</div>
</form>
{% endblock %}
Just in case of anyone wanting to add a confirmation view to something more than an action.
I wanted to make the save of an admin creation view go to a confirmation view. My model was very complex and created a lot of implications for the system. Adding the confirmation view would make sure that the admin was aware of these implications.
The solution would be overriding some _changeform_view method which is called on the creation and the edition.
The full code is here: https://gist.github.com/rsarai/d475c766871f40e52b8b4d1b12dedea2
Here is what worked for me:
Add confirm action method (in admin.py)
from django.template.response import TemplateResponse
def confirm_my_action(modeladmin, request, queryset):
response = TemplateResponse(request,
'admin/confirm_my_action.html',
{'queryset': queryset})
return response
and point to it from your admin model (in admin.py)
class SomeModelAdmin(admin.ModelAdmin):
actions = [confirm_my_action]
Add template, which has a form whose action is pointing to my_action endpoint.
{% extends "admin/base_site.html" %}
{% block content %}
<div id="content" class="colM delete-confirmation">
<form method="post" action="/admin/my_action/">
{% csrf_token %}
<div>
{% for obj in queryset %}
<input type="hidden" name="obj_ids[]" value="{{ obj.pk }}" />
<ul><li>Obj: ">{{obj}}</a></li></ul>
{% endfor %}
</div>
<input type="submit" value="Yes, I'm sure">
No, take me back
</form>
<br class="clear">
<div id="footer"></div>
</div>
{% endblock %}
Add appropriate endpoint (e.g. in urls.py).
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^admin/my_action/', my_action_method),
]