Django: writing a view to delete multiple object with checkboxes - python

So I have a table that lists all the record from my model.
But now I'm trying to make a Checkbox and delete it (kinda like the Django admin way), I can't find the documentation for this , as I'm sure there are several ways to to this.
But I'm trying to figure out like whats the proper way for doing this , should I do this via view ?
How to create single delete button for multiple delete instances in html and view.I am not using form
I refreed this side but not get correct solution
Django: writing a view to delete an item with checkboxes
Deleting multiple rows in Django frontend
list.html
{% for obj in object_list %}
<tbody>
<tr>
<td><input type="checkbox" name="data" value="{{obj.id}}" ></td>
<td><a href='#' data-toggle="collapse" value="{{obj.id}}">{{ obj.id }}</td>
<td>{{ obj.Full_Name }}</td>
<td>{{ obj.Agency_Name}}</td>
<td>{{ obj.Date_of_Birth}}</td>
<td>{{ obj.Agency_Code}}</td>
<td><span class="label label-primary">{{ obj.Agent_Status}}</span></td>
<td class="text-right">
<i class="fa fa-list-alt" aria-hidden="true"></i>
<i class="fa fa-pencil-square-o" aria-hidden="true"></i>
#<i class="fa fa-trash" aria-hidden="true"></i>
#Remove this button and create single button for multiple delete
</td>
</tr>
</tbody>
{% endfor %}
view.py
def Agent_List(request, id=None): #list items
queryset = Agent.objects.order_by('id')
#queryset = Agent.objects.all()
query = request.GET.get('q')
if query:
queryset=queryset.filter(
Q(Aadhaar_Number__icontains=query) |
Q(PAN_Number__icontains=query) |
Q(Account_Number__icontains=query)
).distinct()
context = {
"object_list": queryset,
"Full_Name ": "Agent_List",
}
return render(request, "customer/Agent_List.html", context)
def Agent_Delete(request, id=None):
instance = get_object_or_404(Agent, id=id)
instance.delete()
messages.success(request, "Successfully deleted")
return redirect("customer:Agent_List")
In def Agent_Delete(request, id=None) it delete single id.but How to delete selected multiple id.Thank you in advance.

Related

Can’t loop value in html table

I’m building a function which can let admin to delete account in that page.
I have several accounts in admin page but all the delete buttons are holding a value from first account in that page instead of other account.
<form action="/admin" method="post">
<table class="table">
<thead class="table-dark">
<tr>
<th>Users</th>
</tr>
</thead>
{% for user in users %}
<tr style="background-color:burlywood">
<td><input type="hidden" name="user" value="{{user.username}}">{{user.username}}</td>
<td><input type="submit" for="user" value="Delete"></td>
{% endfor %}
</tr>
</table>
#app.route("/admin", methods=["GET", "POST"])
#login_required
def admin():
"""Manage account"""
if request.method == "GET":
user_id = session["user_id"]
admin = db.execute("SELECT id FROM users WHERE id = (?)",
user_id)
for row in admin:
if int(row["id"]) == 17:
users = db.execute("SELECT username FROM users")
return render_template("admin.html", users = users)
else:
return apology("Only Admin can access this page!")
return apology("valid return")
else:
username = request.form.get("user")
flash(f"{username} has been deleted!")
return redirect("/")
I expected each delete button is holding each value in column.
After the issue is fixed, when delete button is clicked flash function will show the different username based on the value not admin at all.
here is html page
From the tags I believe you're using Jinja to load and render the html page, however, you should be more clear about what you want to ask.
This may sound like a bad idea and definitely something you shouldn't do in production but how about creating different forms for each user?
Something like this :
<table class="table">
<thead class="table-dark">
<tr>
<th>Users</th>
</tr>
</thead>
{% for user in users %}
<form action="/admin" method="post">
<tr style="background-color:burlywood">
<td><input type="hidden" name="user" value="{{user.username}}">{{user.username}}</td>
<td><input type="submit" for="user" value="Delete"></td>
</tr>
</form>
{% endfor %}
</table>
I think your line only returns usernames in your users variable:
users = db.execute("SELECT username FROM users")
So users in your template is an array that only contains a list of names, or only contains one name.
1 / Whats contains users?
2 / what if you put {{ user }} instead of {{ user.username }} in your template?

Flask - cant post to route [duplicate]

This question already has answers here:
Sending data from HTML form to a Python script in Flask
(2 answers)
Closed last year.
I'm creating a configurator app for heating systems. Essentially the idea is by putting in a few inputs - the app will spit out the part number for a system pack where a user can see a detailed bill of material (BOM).
One key element is the output where we need to show a few options. I.e. if someone needs a 200kW system, there could be 3-4 packs that are suitable (190kW -210kW might be more cost effective).
I want in the first instance to show on a route the pack options that are suitable- then the user selects the pack they want- which takes you to a route (/cart) which shows the BOM.
I have put in input variables min and max which searches a database cascades.db. This successfully shows me the table of options.
from cs50 import SQL
from flask import Flask, render_template, request, url_for, redirect
app = Flask(__name__)
db = SQL("sqlite:///cascades.db")
#app.route("/")
def index():
return render_template("index.html")
#app.route("/search", methods=["GET", "POST"])
def search():
output = request.form.get("output")
hydraulic = request.form.get("hydraulic")
layout = request.form.get("layout")
controls = request.form.get("controls")
min_output = int(output) - 15
max_output = int(output) + 15
cascades = db.execute("SELECT * FROM cascades WHERE hydraulic = ? AND layout = ? AND output BETWEEN ? and ?", hydraulic, layout, min_output, max_output)
return render_template("search.html", cascades=cascades)
#app.route("/cart", methods=["GET", "POST"])
def cart():
bom_id = request.form.get("bom_id")
bom = db.execute("SELECT * FROM bom WHERE bom_id = ?", bom_id)
return render_template("bom.html", bom = bom)
When running the app- the first bit works - i.e. it shows me a list of all the packs that meet the criteria- but when clicking the 'Choose' button Im getting stuck.
{% extends "layout.html" %}
{% block body %}
<h3> Boiler Cascade Pack Options:</h3>
<table class="table table-striped table-boardered">
<tr>
<th>Part Number</th>
<th>Description</th>
<th>Number of boilers</th>
<th>BOM</th>
</tr>
{% for cascades in cascades %}
<tr>
<td scope="cascades">{{ cascades["id"] }}</td>
<td>{{ cascades["description"] }}</td>
<td>{{ cascades["number_of_boilers"] }}</td>
<td>
<form action "/cart" method="post">
<input name="bom_id" type="hidden" value="{{ cascades["id"] }}">
<input class="btn btn-primary" type="submit" value="Choose">
</form>
</td>
</tr>
{% endfor %}
</table>
{% endblock %}
But when submitting the form- where they select the pack (which has the pack id number- as a hidden form) I get the following error:
File "/home/ubuntu/cascade2/application.py", line 26, in search
min_output = int(output) - 15 TypeError: int() argument must be a
string, a bytes-like object or a number, not 'NoneType'
It seems like the route is trying to use the same logic in the second search but at this point its redundant. The second search all I want is to show me information where the Pack id = BOM.
I've noticed the URL stays on the (/search) route with this and not going to the (/cart).
I've tried several things such as putting in a IF NOT output- redirect to Cart to try and bi pass this- which successfully loads the bill of material page but nothing comes up as I don't think its posted the id to the route.
I've also changed it to GET instead of POST, which results in the query string /search?bom_id=71723827132. Which shows its picking up the part number- but staying on the /search route where I see the error.
<h3> Boiler Cascade Pack Options:</33>
<table class="table table-striped table-boardered">
<tr>
<th>Part Number</th>
<th>Description</th>
<th>Number of boilers</th>
</tr>
{% for cascade in cascade %}
<tr>
<td scope="cascade">{{ cascades["id"] }}</td>
<td>{{ cascades["description"] }}</td>
<td>{{ cascades["number_of_boilers"] }}</td>
</tr>
{% endfor %}
</table>
<br>
<h4>Bill of material:</h4>
<br>
<table class="table table-striped table-boardered">
<tr>
<th>Product ID</th>
<th>Product Description</th>
<th>Quantity</th>
</tr>
{% for bom in bom %}
<tr>
<td scope="bom">{{ bom["part_number"] }}</td>
<td>{{ bom["product_description"] }}</td>
<td>{{ bom["quantity"] }}</td>
</tr>
{% endfor %}
</table>
Been stuck on this for a month. This to me is the last piece of the puzzle. Any help/suggestions would be great. I'm new to programming so I bet I've missed something obvious :)
Your <form action "/cart" method="post"> is missing an = after action. That means the action attribute is not properly defined, and the default for action always is the URL you're currently on. That's why it stays at /search.

How to download an updated file by admin in Django

what i am trying to do is:
Admin uploads a PDF file from admin panel. (1)
It needs to go to the specified template. (2)
And it should be downloaded by pressing download button in the template.
So here are codes:
(1)
class Reports(models.Model):
name = models.CharField(max_length=100, null=False, blank=False, verbose_name="File Name")
report = models.FileField()
(2)
<tr>
<td>"File Name must be showed in here"</td>
<td class="text-center">PDF</td>
<td class="text-center lang-tr-src"><i class="fas fa-file-download"></i></td>
<td class="text-center lang-en-src"><i class="fas fa-file-download"></i></td>
</tr>
In the website there will be one report for every month. I want to list them in the template and make them downloadable.
Should i write a view for that(if yes how it should be?) or what should i do?
Every single data you want to show to your template you need write it in your views.py, so this case is so specefic.
views.py:
def your_view_name(request):
reports = Reports.objects.all()
context = {
'reports': reports
}
return render(request, 'your_template.html', context)
Then make a url for your view in urls.py
urlpatterns = [
path("", views.your_view_name, name='your_url_name')
]
Your template:
<tr>
{% for obj in reports %}
<td>{{ obj.name }}</td>
<td class="text-center">PDF</td>
<td class="text-center lang-tr-src"><a href="{{ obj.report.url }}" Download
target="_blank"><i class="fas fa-file-download"></i></a></td>
<td class="text-center lang-en-src"><a href="" target="_blank"><i
class="fas fa-file-download"></i></a></td>
{% endfor %}
</tr>
create a new view firstly.
def report_view(request):
context = {}
reports= Reports.objects.all()
context['reports'] = reports
return render(request, "pages/report.html", context)
create an url for this view in urls.py
path('reports', report_view, name='report_view'),
in your template create forloop for this context like below:
{% for report in reports %}
<tr>
<td>"File Name must be showed in here"</td>
<td class="text-center">PDF</td>
<td class="text-center lang-tr-src"><i class="fas fa-file-download"></i></td>
<td class="text-center lang-en-src"><i class="fas fa-file-download"></i></td>
</tr>
{% endfor %}

Displaying Django Admin Navigation on non-model template

I have made an HTML form(with only HTML's form tag, not Django) which I have put inside {% block content %} for Django to display.
{% extends "admin/base_site.html" %}
{# mainapp/templates/VideoTracker.html #}
{% block content_title %}
{{ 'Execution Status' }}
{% endblock %}
{% block content %}
<form>
<table> <br>
<tr>
<td>
<div>
<input type="checkbox" name="adhocexec", value="Adhoc" checked/> Adhoc Request
</div>
</td>
<td>
<div>
<input type="checkbox" name="periodicexec", value="Periodic" checked> Periodic Request
</div>
</td>
</tr>
<tr>
<td>
<div>
Start : <input type="date" name="frdt">
</div>
</td>
<td>
<div>
End : <input type="date" name="todt">
</div>
</td>
</tr>
</table>
<br>
<div>
<button type="submit" class="btn btn-primary"> <span class="glyphicon glyphicon-search"></span> Search Reports </button>
</div>
<br>
<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search in results..." title="Type Here">
<table id="myTable">
<tr class="header">
<th>BOX ID</th>
<th>MSO ID</th>
<th>Execution Type</th>
<th>Channel ID</th>
<th>Execution Date Time</th>
<th>Result</th>
<th>Detailed Report</th>
</tr>
{% for queue in results %}
<tr>
<td>{{ queue.box_id }}</td>
<td>{{ queue.mso_id }}</td>
<td>{{ queue.exec_type }}</td>
<td>{{ queue.channel_id }}</td>
<td>{{ queue.exec_time }}</td>
<td>{{ queue.result_status }}</td>
<td>{{ queue.result_link }}</td>
</tr>
{% endfor %}
</table>
<script>
function myFunction()
{
var input, filter, table, tr, td, i;
input = document.getElementById("myInput");
filter = input.value.toUpperCase();
table = document.getElementById("myTable");
tr = table.getElementsByTagName("tr");
for (i = 0; i < tr.length; i++)
{
td_col0 = tr[i].getElementsByTagName("td")[0];
td_col1 = tr[i].getElementsByTagName("td")[1];
td_col2 = tr[i].getElementsByTagName("td")[2];
td_col3 = tr[i].getElementsByTagName("td")[3];
td_col4 = tr[i].getElementsByTagName("td")[4];
td_col5 = tr[i].getElementsByTagName("td")[5];
td_col6 = tr[i].getElementsByTagName("td")[6];
if (td_col0 && td_col1 && td_col2 && td_col3 && td_col4 && td_col5 && td_col6)
{
cond0 = td_col0.innerHTML.toUpperCase().indexOf(filter) > -1
cond1 = td_col1.innerHTML.toUpperCase().indexOf(filter) > -1
cond2 = td_col2.innerHTML.toUpperCase().indexOf(filter) > -1
cond3 = td_col3.innerHTML.toUpperCase().indexOf(filter) > -1
cond4 = td_col4.innerHTML.toUpperCase().indexOf(filter) > -1
cond5 = td_col5.innerHTML.toUpperCase().indexOf(filter) > -1
cond6 = td_col6.innerHTML.toUpperCase().indexOf(filter) > -1
if (cond0 || cond1 || cond2 || cond3 || cond4 || cond5 || cond6)
{
tr[i].style.display = "";
}
else
{
tr[i].style.display = "none";
}
}
}
}
</script>
</form>
{% endblock %}
I have linked this HTML on urls.py and from my views.py I am calling a function which does some processing and displays data on the HTML. So far so good.
Now I wanted to display this HTML on admin as a link, ideally, all Class Model is shown as the link on Admin but for my case, the data which I am presenting is non-model. So to display this as a clickable link on Admin I made test model on models.py
class TestModel(models.Model):
try:
print('TestModel')
except Exception as ex:
logging.error('Exception : models --> TestModel ' + str(ex))
And in my admin.py I made class with base AdminViews
class TestAdmin(AdminViews):
admin_views = (
('Track Executions', 'redirect_to_executions'),
)
def get_model_perms(self, request):
"""
Return empty perms dict thus hiding the model from admin index.
"""
return {}
def redirect_to_executions(self, *args, **kwargs):
return redirect('/track_execution')
With this, I am able to see link on the Admin page
After clicking the link, I see default admin page like I am not logged in.
How can I make my logged in details i.e. same context to persist as with model links to be shown on my non-model template as well?
I am a bit struggling with it.
You can use do it at the lazy way or the hard way...
The lazy way Build onde Proxy Models, so that way he wont persist the data, and you can show it as any other models in admin, and change what you want to do with it at your admin view
Proxy Models: https://docs.djangoproject.com/en/2.0/topics/db/models/#proxy-models
The Hard way You can override this template and add it manualy with the same classes and css stuffs to looks like the others.
Override Template: https://docs.djangoproject.com/en/dev/ref/contrib/admin/#overriding-admin-templates
Maybe there is other simple way to do that, if you find one better please share :)

Django: Receiving data from dynamic form value field

Working on converting an app from Flask to Django and getting stuck on how I can pull data from the value of a form button. I have some data that is rendered in a table with a for loop. Each entry has a button displayed that allows my to flip an integer field for the rendered data. Once it's flipped, it's no longer listed.
# manage.html
{% for ticket in tickets %}
<tr>
<td>{{ my_obj.id }}</td>
<td>{{ my_obj.tt }}</td>
<td>{{ my_obj.user }}</td>
<td>{{ my_obj.time }}</td>
<td><form action="/flip/" method="post">{% csrf_token %}
<input type="hidden" name="flip" value="{{ my_obj.id }}"/>
<input type="submit" class="btn btn-xs btn-danger" value="Kill"/>
</form>
</td>
</tr>
{% endfor %}
# views.py
def flip(request):
if request.method == 'POST':
tt_id = request.POST.get('value')
return HttpResponse(tt_id )
def manage(request):
my_obj = MyObject.objects.filter(status=1)
return render(request, 'manage.html', {'my_obj': my_obj})
Currently I am getting a response of None rather than the actual ID which is showing in the value field with firebug.
Thanks for looking!
You have to access the fields by the name, not with value. e.g.
request.POST.get('flip')
If you want to access the buttons value, you need to set the name attribute on it.
For details on your request it is helpful for print or return the whole request object. A debugger would be an other way to take a look at it.

Categories

Resources