Django Formset Delete Field Not Showing - django

I need to manually render my formset in my template and I cannot get the delete checkbox field into the template when I render manually. However, it does show when I render {{form.as_table}}.
views.py
QuoteManifestForm= modelformset_factory(QuoteManifest, QManifestForm, can_delete = True)
template - this does not display the {{form.DELETE}} but every other field shows fine, including id which I can see in the DOM.
{{ manifest.management_form }} <--!I passed QuoteManifestForm to template as 'manifest'-->
{% for form in manifest.forms %}
<div id="form_set">
<table id = 'manifest-table25' class="manifest-table2" width=100%>
{% csrf_token %}
<tbody width=100%>
<tr class="manifest-row">
<td width = 17.5% class="productCode" onchange="populateProduct(this)">{{form.ProductCode}}</td>
<td width = 32.5% class="description">{{form.DescriptionOfGoods}}</td>
<td width = 12.5% class="quantity" oninput="calculateUnit(this)">{{form.UnitQty}}</td>
<td width = 12.5% class="unitType">{{form.Type}}</td>
<td width = 12.5% class="price" oninput="calculate(this)">{{form.Price}}</td>
<td width = 12.5% class="amount2">{{form.Amount}}</td>
<td>{{form.DELETE}}</td>
{{form.id}}
</tr>
</tbody>
</table>
</div>
{% endfor %}
Any idea why that is not working?
UPDATE:
I found in the django docs that if you are rendering manually, you should include something like the below in your form. I tried this, but still no Delete field appears in my template:
{% if form2.can_delete %}
<td> {{form.DELETE}}</td>
{% endif %}
CODE TO REPRODUCE
views.py
def QuoteView(request):
QuoteManifestForm= modelformset_factory(QuoteManifest, fields =('ProductCode', 'DescriptionOfGoods', 'UnitQty', 'Type','Amount', 'Price'), can_delete = True)
if request.method == "POST":
form2 = QuoteManifestForm(request.POST)
form2.save()
return redirect('HomeView')
else:
form2 = QuoteManifestForm()
context = {
'form2': form2,
}
return render(request, 'quote.html', context)
quote.html
{{ form2.management_form }}
<div id="form_set">
{% for form2 in form2.forms %}
<table id = 'manifest-table25' class="manifest-table2" width=100%>
{% csrf_token %}
<tbody width=100%>
<tr class="manifest-row">
<td width = 17.5% class="productCode" onchange="populateProduct(this)">{{form2.ProductCode}}</td>
<td width = 32.5% class="description">{{form2.DescriptionOfGoods}}</td>
<td width = 12.5% class="quantity" oninput="calculateUnit(this)">{{form2.UnitQty}}</td>
<td width = 12.5% class="unitType">{{form2.Type}}</td>
<td width = 10.5% class="price" oninput="calculate(this)">{{form2.Price}}</td>
<td width = 12.5% class="amount2">{{form2.Amount}}</td>
<td>{{form2.DELETE}}</td>
{{form2.id}}
</tr>
</tbody>
</table>
{% endfor %}
</div>
models.py
class QuoteManifest(models.Model):
ProductCode = models.ForeignKey(Product, null=True, blank=True)
DescriptionOfGoods = models.CharField(max_length=500, blank=True)
UnitQty = models.CharField(max_length=10, blank=True)
Type = models.CharField(max_length=50, blank=True)
Amount = models.CharField(max_length=100, blank=True)
Price = models.CharField(max_length=100, blank=True)
{{form2.DELETE}} is supposed to render a checkbox. This is what I cannot get working. It does work when I render the form as {{form2.as_p}} but that will not work for me in my case.

Using your example code, I was able to create a sample that seems to render the checkbox using the {{ form.DELETE }} syntax.
It appears that my sample code is very similar to what you already have. I did add an on_delete parameter to the ProductCode variable in the QuoteManifest model. And I'm not sure what your Product model looks like so I just created a dummy model. I also removed your CSS classes and JavaScript calls. Is it possible that something in your JavaScript was overriding the checkboxes?
As you'll see in my sample, I do get the checkbox. My code is below, and here is a link to the working demo on repl.it.
models.py
from django.db import models
class Product(models.Model):
ProductName = models.CharField(max_length=100, unique=True)
class QuoteManifest(models.Model):
ProductCode = models.ForeignKey(Product, null=True, blank=True, on_delete=models.CASCADE)
DescriptionOfGoods = models.CharField(max_length=500, blank=True)
UnitQty = models.CharField(max_length=10, blank=True)
Type = models.CharField(max_length=50, blank=True)
Amount = models.CharField(max_length=100, blank=True)
Price = models.CharField(max_length=100, blank=True)
views.py
from django.shortcuts import render, redirect
from django.forms.models import modelformset_factory
from .models import QuoteManifest
def QuoteView(request):
QuoteManifestForm= modelformset_factory(QuoteManifest, fields =('ProductCode', 'DescriptionOfGoods', 'UnitQty', 'Type','Amount', 'Price'), can_delete=True)
form2 = QuoteManifestForm()
context = {
'form2': form2,
}
return render(request, 'quote.html', context)
templates/quote.html
<div id="form_set">
{% for form2 in form2.forms %}
<table id="manifest-table25" width=100%>
{% csrf_token %}
<tbody width=100%>
<tr>
<td>{{form2.ProductCode}}</td>
<td>{{form2.DescriptionOfGoods}}</td>
<td>{{form2.UnitQty}}</td>
<td>{{form2.Type}}</td>
<td>{{form2.Price}}</td>
<td>{{form2.Amount}}</td>
<td>{{form2.DELETE}}</td>
</tr>
</tbody>
</table>
{% endfor %}
</div>

Based on the examples here: https://docs.djangoproject.com/en/3.0/topics/forms/formsets/#manually-rendered-can-delete-and-can-order
It looks like your view would be:
def QuoteView(request):
QuoteManifestFormset= modelformset_factory(QuoteManifest, fields =('ProductCode', 'DescriptionOfGoods', 'UnitQty', 'Type','Amount', 'Price'), can_delete = True) # Renamed as formset for clarity
if request.method == "POST":
formset = QuoteManifestFormset(request.POST) # also renamed
formset.save()
return redirect('HomeView')
else:
formset = QuoteManifestFormset()
context = {'formset': formset}
return render(request, 'quote.html', context)
And your quote.html I think {% for form2 in form2.forms %} needs to be {% for form in formset %}
<form method="post">
{{ formset.management_form }}
{% for form in formset %}
<table id = 'manifest-table25' class="manifest-table2" width=100%>
{% csrf_token %}
<tbody width=100%>
<tr class="manifest-row">
<td width = 17.5% class="productCode" onchange="populateProduct(this)">{{form.ProductCode}}</td>
<td width = 32.5% class="description">{{form.DescriptionOfGoods}}</td>
<td width = 12.5% class="quantity" oninput="calculateUnit(this)">{{form.UnitQty}}</td>
<td width = 12.5% class="unitType">{{form.Type}}</td>
<td width = 10.5% class="price" oninput="calculate(this)">{{form.Price}}</td>
<td width = 12.5% class="amount2">{{form.Amount}}</td>
<td>{{form.DELETE}}</td>
{{form.id}}
</tr>
</tbody>
</table>
{% endfor %}
</form>

Related

How to check if the object is assigned to another object | Django

I am working on a django case like below:
models.py
class Room(models.Model):
name = models.CharField("Room No.",max_length=200)
class Meta:
verbose_name_plural = "Room"
def __str__(self):
return self.name
class Student(models.Model):
name = models.CharField("name",max_length=200)
father_name = models.CharField("father Name",max_length=200)
cell_no = models.CharField("cell No",max_length=200)
address = models.CharField("address",max_length=500)
room = models.ForeignKey(Room, on_delete=models.CASCADE, null=True, blank=True, related_name='all_rooms')
class Meta:
verbose_name_plural = "Student"
def __str__(self):
return self.name
views.py
def room(request):
allrooms= Room.objects.all()
form = RoomForm(request.POST or None, request.FILES or None)
if form.is_valid():
form.save()
messages.success(request, "Room added successfully.")
return redirect('/room')
context = {'allrooms':allrooms, 'form':form}
return render(request, 'room.html', context)
In templates in room.html I want to show the status Vacant/Occupied based on the fact if a room is assigned to some student or not. I have the following code in template but it shows 'Vacant' status for all rooms.
<table id="example1" class="table table-bordered table-striped">
<thead>
<tr>
<th>Room</th>
<th class="text-center">Status</th>
<th class="text-center">Action</th>
</tr>
</thead>
<tbody>
{% for room in allrooms %}
<tr>
<td>{{ room.name }}</td>
<td class="text-center">
{% if room.student_set.all %}
<small class="badge badge-danger">Occupied</small>
{% elif not room.student.all %}
<small class="badge badge-success">Vacant</small>
{% endif %}
</td>
<td class="text-center"><i class="fas fa-edit"></i></td>
</tr>
{% endfor %}
</tbody>
</table>
Please help someone to show he status of the room.
to get assigned and unassigned rooms you have to write queries with respect to the related field(in this case the foreign key "all_rooms") as follows:
total_rooms = Room.objects.all().annotate(num_rooms=Count("all_rooms"))
assigned_rooms = total_rooms.filter(num_rooms__gt=0)
unassigned_rooms = total_rooms.exclude(num_rooms__gt=0)
On running, these queries will return the room instances:

Error during template rendering Reverse for 'group-edit' not found. 'group-edit' is not a valid view function or pattern name

I ve an error when loading 'group_list.html' :
Reverse for 'group-edit' not found. 'group-edit' is not a valid view function or pattern name.
If I supress this href reference, it works but I need this to be able to edit a group instance
this is my views.py for group_edit:
def group_edit(request, group_id):
group_form = GroupFormEdit(instance=Group.objects.get(id=group_id))
if request.method == "POST":
group_form = GroupForm(request.POST, instance=Group.objects.get(id=group_id))
if group_form.is_valid():
group_form.save()
messages.success(request, 'Group saved') # message for inform user of success - See messages in html file
return redirect('home')
else:
group_form = GroupForm()
return render(request, 'imports/group_edit.html', {
"group_form": group_form,
})
my group_list.html:
{% block page %}
<div class="panel-body">
<table class="table table-bordered table-hover table-striped col-md-3">
<thead class="thead-dark">
<tr class="text-center">
<th>Group Name</th>
<th>Parent Name</th>
</tr>
</thead>
<tbody>
{% for group in groups %}
<tr>
<td scope="row" class="col-md-3">{{ group.group_name }}</td>
<td class="col-md-3">{{ group.groupParent_id }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}
my urls.py:
urlpatterns = [
path('', views.imports_last, name='home'),
path('company_create/', views.company_create, name='company_creation'),
path('group_create/', views.group_create, name='group_creation'),
path('group_edit/', views.group_edit, name='group_edit'),
path('group_list/', views.group_list, name='group_list'),
]
and models.py:
class Group(models.Model):
group_id = models.AutoField(primary_key=True)
groupParent_id = models.ForeignKey('self', blank=True, null=True, related_name='Parent', on_delete=models.CASCADE)
group_name = models.CharField(max_length=100, null=False, blank=False, unique=True)
def __str__(self):
return '{}'.format(self.group_name)
I find my pain point;
it is in the url
I should mention that I want to add a variable :
path('group_edit/<int:group_id>/', views.group_edit, name='group-edit'),

Select data from drop-down list and save it to database in Django

I am a newbie in Django. I want to show the food_status in drop-down list options, therefore the chef can select one of them, change it, and update it into database. It can be updated into database, but i am not sure how to display the drop-down list on template based on the food_status that I have in models.py.
Anyone know how to do it?
models.py
class OrderItem(models.Model):
Table_No = models.IntegerField(blank=False)
FoodId = models.TextField()
Item = models.TextField()
Qty = models.DecimalField(max_digits=5, decimal_places=0)
Price = models.DecimalField(max_digits=10, decimal_places=2)
TotalPrice = models.TextField()
Note = models.TextField(max_length=100, null=True)
OrderId = models.TextField(max_length=5, null=True)
FoodStatus = (
('1', 'Has been ordered'),
('2', 'cooked'),
('3', 'ready to be served'),
('4', 'done'),
)
food_status = models.CharField(max_length=50, choices=FoodStatus)
views.py
def see_order(request):
if request.method == "POST":
OrderId = request.POST.get("OrderId")
customerOrder = OrderItem(OrderId=OrderId)
so = OrderItem.objects.filter(OrderId=OrderId)
return render(request, 'restaurants/see_order.html', {'so': so})
else:
return render(request, 'restaurants/customer_page.html')
see_order.html
<form action="#" method="post">
<style>
table, th, td {
border: 1px solid black;
table-layout: fixed ;
height: "2000" ;
width: "2000" ;
}
</style>
{% csrf_token %}
{% for order in so %}
<table>
<tr>
<th>Table Number</th>
<th>Item</th>
<th>Quantity</th>
<th>Status</th>
<th>Order Id</th>
</tr>
<tr>
<td>{{ order.Table_No }}</td>
<td>{{ order.Item }}</td>
<td>{{ order.Qty }}</td>
<td>{{ order.food_status }}</td>
<td>{{ order.OrderId }}</td>
</tr>
{% endfor %}
</table>
<br><input action="action" onclick="window.history.go(-1); return false;" type="button" value="Back"></br>
</form>
The kitchen_page template should show the drop-down list, then the chef can choose the food_status from that drop-down list, click save button, and update the database.
You can render choices using {% for %} loop and FoodStatus list of choices like this:
<td>
{{ order.get_food_status_display }}
<select name="food_status">
{% for id, choice in order.FoodStatus %}
<option value="{{ id }}"{% if order.food_status == id %} selected="selected"{% endif %}>{{ choice }}</option>
{% endfor %}
</select>
</td>
You can display actual status text (instead of id), using get_FOO_display method.
Added {% if %} tag to preselect correct option.
Consider switching to Forms so it can handle rendering fields automatically.(!!!)
Consider switching food_status to IntegerField instead. Provide default attribute, so it will always be one of the choices, even if not specified.
Try using choices attribute of Django fields https://docs.djangoproject.com/en/2.0/ref/models/fields/#choices

Display a form and the output on the same page

This code will display the form. I can input data, submit the data and the data then displays along with the previous input data from the mySQL DB table where the dat is written, but when the data displays the input form goes away (all expect the submit button that is). I've come across this subject here, but could never quite find the answer that worked for me.
**`models.py`**
class UnitPool(models.Model):
# rack = models.ForeignKey(Rack)
# platform = models.ForeignKey(Group)
location = models.CharField(max_length=10, choices=LAB, default='Choose', blank=False)
rack = models.CharField(max_length=10, choices=RACKS, default='Choose', blank=False)
platform = models.CharField(max_length=10, choices = PLATFORM, default='Choose',blank=False)
unit_HW_Serial = models.CharField(max_length=20, blank=False, null=False)
unit_SW_Serial = models.CharField(max_length=20, blank=False, null=False)
unit_SKU = models.CharField(max_length=20, blank=False, null=False)
comments = models.CharField(max_length=64, blank=True, null=True, default='')
def __unicode__(self): # __unicode__ on Python 2
return '%s %s %s %s %s %s' % (self.rack,
self.platform,
self.unit_HW_Serial,
self.unit_SW_Serial,
self.unit_SKU,
self.comments)
class UUTForm(ModelForm):
class Meta:
model = UnitPool
widgets = {
'comments': TextInput(attrs={'size': 10}),
}
fields = ['location','rack', 'platform','unit_HW_Serial','unit_SW_Serial','unit_SKU','comments']
**forms.html**
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="container">
<div class='row'>
<div class='col-md-2'>
{% if title %}
<h1 class='{% if title_align_center %}text-align-center{% endif %}'>{{ title }}</h1>
{% endif %}
<form method='POST' action=''>{% csrf_token %}
{{ form|crispy }}
<input class='btn btn-primary' type='submit' value='Add Unit' />
</form>
</div>
</div>
</div>
{% if queryset %}
{% if rack != '' %}
<div class="container">
<div class="row">
<div class='col-md-8 col-md-offset-3'>
<h1>Unit Data Entered</h1>
<table class='table'>
<td><b>Item</b></td>
<td><b>Location</b></td>
<td><b>Rack#</b></td>
<td><b>Platform</b></td>
<td><b>HW SN</b></td>
<td><b>SW SN</b></td>
<td><b>SKU</b></td>
<td><b>Comment</b></td>
{% for instance in queryset %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ instance.location }}</td>
<td>{{ instance.rack }}</td>
<td>{{ instance.platform }}</td>
<td>{{ instance.unit_HW_Serial }}</td>
<td>{{ instance.unit_SW_Serial }}</td>
<td>{{ instance.unit_SKU }}</td>
<td>{{ instance.comments }}</td>
</tr>
{% endfor %}
</table>
</div>
</div>
</div>
{% endif %}
{% endif %}
{% endblock %}
**views.py**
from django.conf import settings
from django.shortcuts import render
from .models import UnitPool, UUTForm
def labunits(request):
title = 'Enter Info'
form = UUTForm(request.POST or None)
context = {
"title": title,
"form": form
}
if form.is_valid():
instance = form.save(commit=False)
instance.save()
queryset = UnitPool.objects.all().order_by('rack','platform')
context = {
"queryset": queryset
}
return render(request, "labunits/forms.html", context)
You need to pass the form in the context after calling .is_valid() as #Daniel also mentioned.
Since you are not passing the form in the context again after calling the .is_valid() function, the form does not get displayed again in the template.
So, when you are resetting the context, you need to pass the form also.
def labunits(request):
title = 'Enter Info'
form = UUTForm(request.POST or None)
context = {
"title": title,
"form": form
}
if form.is_valid():
instance = form.save(commit=False)
instance.save()
queryset = UnitPool.objects.all().order_by('rack','platform')
context = {
"queryset": queryset,
"form" : form # pass the form in the context
}
return render(request, "labunits/forms.html", context)

author = models.ForeignKey('auth.User', null=True, blank=False) trouble

I have a table where I save data(description, x, y, result and creation date) and until now everything works.
I thought then to add a column with the author for each saved line eg:
DES| X | Y | RESULT |CREATION DATE| AUTHOR |
hi | 3| 1 | 4 | 24/02/2015 | username |
then I added in models.py auth:
from django.db import models
from django.utils import timezone
from simpleapp.oper import add_divide
from django.conf import settings
class ElementiTab(models.Model):
author = models.ForeignKey('auth.User', null=True, blank=False)
des = models.CharField(max_length=30)
x = models.FloatField()
y = models.FloatField()
res = models.FloatField(default=0)
created_date = models.DateTimeField(default=timezone.now)
def save(self, *args, **kwargs):
self.res = add_divide(self.x, self.y)
super(ElementiTab, self).save(*args, **kwargs)
def __str__(self):
return self.des
UPDATE:
forms.py
from django import forms
from .models import ElementiTab
class ElementiTabForm(forms.ModelForm):
class Meta:
model = ElementiTab
fields = ('des', 'x', 'y')
views.py
#login_required
def tabval(request):
# if this is a POST request we need to process the form data
valori = ElementiTab.objects.filter().order_by('-created_date')
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = ElementiTabForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
form.save()
# if a GET (or any other method) we'll create a blank form
else:
form = ElementiTabForm()
return render(request, 'simpleapp/simpleapp.html', {'form': form, 'valori': valori})
#user_passes_test(lambda u: u.is_superuser)
def delete(request, id):
valori_to_delete = get_object_or_404(ElementiTab, pk=id).delete()
return redirect(tabval)
simpleapp.html
{% extends 'registration/base_reg.html' %}
{% block title %}SimpleApp-tabval{% endblock %}
{%block content%}
<h4>TABELLA CON DATI</h4>
<form action="/simpleapp/" method="post">
{% csrf_token %}
{{ form.as_table }}
<input type="submit" value="LIST" />
</form>
<form action="/simpleapp/" method="DELETE">
{% csrf_token %}
<input type="submit" name="canc" value="RESET" />
</form>
<br />
<br />
<div class="table-responsive">
<table class="table table-bordered">
<tr class="info">
<td width="15%" align="center"> NOME</td>
<td width="15%" align="center"> X </td>
<td width="15%" align="center"> Y </td>
<td width="15%" align="center"> RISULTATO </td>
<td width="15%" align="center"> DATA CREAZIONE </td>
<td width="15%" align="center"> AUTORE </td>
{% for elementi in valori %}
<div class="elementi">
<tr>
<td>{{elementi.des}}</td>
<td>{{elementi.x}}</td>
<td>{{elementi.y}}</td>
<td>{{elementi.res}}</td>
<td>{{elementi.created_date}}</td>
<td>{{elementi.author}}</td>
<td width="1%">
{% if user.is_superuser %}
Delete
{% else %}
<span style='font-size: small'>Only Admin</span>
{% endif %}
</td>
</div>
{% endfor %}
</table>
</div>
{% endblock content %}
The fact is that the admin page displays a drop-down menu from which I (as administrator) can choose one of the registered user and so I add them both in the table of my app and in the db.
How can I make this process automatic? I.e. after the login, you put data in the table and once saved the data, also the username is saved and should not be the administrator to set it.
I searched a similar question here but I have not found one to help me to solve my problem.
I updated my answere, i misenderstood your question.
Change this in your view
if form.is_valid():
# Creating the object without commiting to database
obj = form.save(commit=False)
# Setting the user from request
obj.author = request.user
# Commiting to the database
obj.save()