Use django formset for only a few specific fields - django

I am relatively new to django (about 3 months using it) and ran into the following problem at work. I have a model with several fields, and they asked me that of those fields, 4 specifically should be able to dynamically add another register, that is, if i register something in one of those fields, there should be the option to do it again indefinitely. I understand that this can be achieved using formset but all the examples I find are using all the fields of the model and not just a few. Any ideas on what I can do?
this is the model
class Mercancia(SafeDeleteModel):
_safedelete_policy = SOFT_DELETE_CASCADE
id = models.AutoField(primary_key=True)
factura = models.ForeignKey("Factura", on_delete=models.CASCADE)
desc_mercancia = models.CharField(max_length=256, validators=[RegexValidator(r'^[0-9a-zA-Z\s]*$', 'La descripción de la mercancia no acepta caracteres especiales.')])
comercio = models.ForeignKey("ClaveComercio", on_delete=models.CASCADE)
tipo_moneda = models.ForeignKey("Moneda", on_delete=models.CASCADE)
cantidad_comerc = models.DecimalField(max_digits=30, decimal_places=0)
valor_unitario = models.DecimalField(max_digits=22, decimal_places=6, validators=[MinValueValidator(0)])
valor_total = models.DecimalField(max_digits=22, decimal_places=6, validators=[MinValueValidator(0)])
valor_total_dolares = models.DecimalField(max_digits=20, decimal_places=4, validators=[MinValueValidator(0)])
marca = models.CharField(blank = True, max_length=35, validators=[RegexValidator(r'^[0-9a-zA-Z\s]*$', 'El modelo solo permite valores alfanuméricos.')])
modelo = models.CharField(blank = True, max_length=50, validators=[RegexValidator(r'^[0-9a-zA-Z\s]*$', 'El modelo solo permite valores alfanuméricos.')])
submodelo = models.CharField(blank=True, max_length=50, validators=[RegexValidator(r'^[0-9a-zA-Z\s]*$', 'El submodelo solo permite valores alfanuméricos.')])
numero_serie = models.CharField(blank = True, max_length=25, validators=[RegexValidator(r'^[0-9a-zA-Z\s]*$', 'El numero de serie solo permite valores alfanuméricos.')])
history = HistoricalRecords()
created_by = models.ForeignKey('catalogos_modular.User', related_name='+', on_delete=models.CASCADE)
updated_by = models.ForeignKey('catalogos_modular.User', related_name='+', on_delete=models.CASCADE, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True, null=True)
class Meta:
# verbose_name = "Mercancia"
# verbose_name_plural = "Mercancias"
db_table = "fac_mercancia"
ordering = ['-id']
view
class CreateMercancia(CreateView):
model = Mercancia
template_name = "mercancias/create.html"
form_class = MercanciaForm
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["mercancia"] = self.model.objects.filter(factura=self.kwargs['pk']).values()
moneda = Moneda.objects.all()
for merch in context['mercancia']:
for mon in moneda:
if merch['tipo_moneda_id'] == mon.id:
merch['tipo_moneda_id'] = mon.name
context["id_anterior"] = self.kwargs['pk']
return context
def get_form_kwargs(self, *args, **kwargs):
form_kwargs = super().get_form_kwargs(*args, **kwargs)
user = self.request.user
form_kwargs['user'] = user
return form_kwargs
def get_success_url(self):
return reverse_lazy('facturas:createMercancias', kwargs={'pk':self.kwargs['pk']})
form
class MercanciaForm(forms.ModelForm):
class Meta:
model = Mercancia
fields = '__all__'
exclude = ('created_by','updated_by','is_deleted','deleted_at')
widgets = {
'desc_mercancia': forms.TextInput(attrs={'placeholder': 'Descripcion de la mercancia'}),
'tipo_moneda': forms.Select(),
'cantidad_comerc': forms.NumberInput(attrs={'placeholder': 'Cantidad de unidades de comercialización'}),
'valor_unitario': forms.TextInput(attrs={'placeholder': 'Valor unitario'}),
'valor_total': forms.TextInput(attrs={'placeholder': 'Valor total'}),
'valor_total_dolares': forms.TextInput(attrs={'placeholder': 'Valor total en dolares'}),
'marca': forms.TextInput(attrs={'placeholder': 'Marca'}),
'modelo': forms.TextInput(attrs={'placeholder': 'Modelo'}),
'submodelo': forms.TextInput(attrs={'placeholder': 'Submodelo'}),
'numero_serie': forms.TextInput(attrs={'placeholder': 'Número de serie'}),
'consecutivo_merc' : forms.TextInput(attrs={'readonly': 'readonly'}),
}
labels = {
'desc_mercancia':'Descripción',
'comercio':'Clave medida de comercialización',
'tipo_moneda':'Tipo de moneda',
'cantidad_comerc':'Cantidad de unidades de comercialización',
'valor_unitario':'Valor unitario',
'valor_total':'Valor total',
'valor_total_dolares':'Valor total en dolares',
'marca':'Marca',
'modelo':'Modelo',
'submodelo':'Submodelo',
'numero_serie':'Número de serie',
'clave_medida_comer':'Clave medida comer.'
}
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user')
super().__init__(*args, **kwargs)
def save(self, commit=True):
self.instance.created_by = self.user
self.instance.updated_by = self.user
if self.instance.id is not None:
self.instance.updated_by = self.user
return super().save(commit=commit)
template create.html
{% load crispy_forms_tags %}
<section class="clean-block clean-form dark" style="overflow-x: auto; ">
<div class="container" >
<div class="row" style="margin-right: 0px;margin-left: 0px;">
<div class="col-md-12"
style="margin-bottom: 25px;padding-left: 5%;font-size: 21px;margin-top: 26px;">
{% if hiddentable != True %}
<a class="anone" href="{% url 'facturas:createPersona' id_anterior %}">
<i class="fa fa-arrow-left" style="color: #6F7271"></i>
<span style="color: #6F7271"> Volver</span>
</a>
{% else %}
<a class="anone" href="{% url 'facturas:editFactura' id_anterior %}">
<i class="fa fa-arrow-left" style="color: #6F7271"></i>
<span style="color: #6F7271"> Volver</span>
</a>
{% endif %}
</div>
</div>
<div class="block-heading" style="padding-top: 0px;">
<h2 class="text_color">
Agregar mercancia
<br>
</h2>
</div>
<form action="" class="tipo_documento" role="form" method="post"
enctype="multipart/form-data" id="factura_form" style="border-top: 2px solid #691C32; width: 1400px; overflow-x: auto;">
{% csrf_token %}
<h3 style="padding-bottom: 12px;">Datos de la mercancia</h3>
<div class="first_container">
<!-- Start: Id de factura -->
<div class="form-group mb-3" hidden>
<input class="form-control" type="text" name="factura" value={{id_anterior}} readonly></input>
</div>
<!-- End: Id de factura -->
<div class="form-group mb-3" >
<strong>{{form.desc_mercancia |as_crispy_field}}</strong>
</div>
<div class="form-group mb-3" >
<strong>{{form.comercio |as_crispy_field}}</strong>
</div>
<div class="form-group mb-3" >
<strong>{{form.tipo_moneda |as_crispy_field}}</strong>
</div>
<div class="form-group mb-3" >
<strong>{{form.cantidad_comerc |as_crispy_field}}</strong>
</div>
<div class="form-group mb-3" >
<strong>{{form.valor_unitario |as_crispy_field}}</strong>
</div>
<div class="form-group mb-3" >
<strong>{{form.valor_total |as_crispy_field}}</strong>
</div>
<div class="form-group mb-3" >
<strong>{{form.valor_total_dolares |as_crispy_field}}</strong>
</div>
<div class="form-group mb-3" >
<strong>{{form.marca |as_crispy_field}}</strong>
</div>
<div class="form-group mb-3" >
<strong>{{form.modelo |as_crispy_field}}</strong>
</div>
<div class="form-group mb-3" >
<strong>{{form.submodelo |as_crispy_field}}</strong>
</div>
<div class="form-group mb-3" >
<strong>{{form.numero_serie |as_crispy_field}}</strong>
</div>
<div class="form-group mb-3" >
<button onClick="this.form.submit(); this.disabled=true; this.value='Sending…'; " id="submit_button" class="btn btn-primary" type="submit" style="background-color: #691C32; border: none;">Guardar</button>
</div>
</div>
{% if hiddentable != True %}
<!-- Start: Tabla personas-->
<div class="mb-3 mt-0" id="lista_personas">
<div class="table_tittle">
<p>Lista de mercancias</p>
</div>
<div class="table_nav_container">
<div class="table_nav2">
<div class="number_page" id="number_page">1</div>
<button type="button" class="back_beggin" id="first_one">&#60 &#60</button>
<button type="button" class="back_one" id="back_one">&#60</button>
<div class="current_page" id="current_page">1</div>
<button type="button" class="next_one" id="next_one">&#62</button>
<button type="button" class="last_one" id="last_one">&#62 &#62</button>
<select class="select_number" name="" id="number_show_select">
<option value="5" selected="selected">5</option>
<option value="10">10</option>
<option value="15">15</option>
<option value="20">20</option>
<option value="25">25</pption>
</select>
</div>
</div>
<div class="row mt-4">
<div class="col-12">
<div class="table-responsive shadow" style="border-radius: 20px;border-style: none;">
<table id="ipi-table" class="table table-striped table-borderless table tablesorter">
<thead class="thead-dark">
<tr>
<th class="text-center">ID Mercancia</th>
<th class="text-center">ID Documento</th>
<th class="text-center">Descripción</th>
<th class="text-center">Clave de la unidad de medida de comercializacion</th>
<th class="text-center">Tipo moneda</th>
<th class="text-center">Cantidad unidades de comercializacion</th>
<th class="text-center">Valor unitario</th>
<th class="text-center">Valor total</th>
<th class="text-center">Valor total dolares</th>
<th class="text-center">Marca</th>
<th class="text-center">Modelo</th>
<th class="text-center">Submodelo</th>
<th class="text-center">Número de serie</th>
<th class="text-center filter-false sorter-false">Acciones</th>
</tr>
</thead>
<tbody id="mercancias_table" class="text-center" hx-get="{% url 'facturas:listaMercancias' id_anterior %}" hx-trigger="load, merchListChanged from:body">
</tbody>
</table>
</div>
</div>
</div>
</div>
{% endif %}
<!-- End: Tabla personas-->
<hr>
{% if hiddentable != True %}
<a class="btn btn-primary" href="{% url 'facturas:createUsuarioFactura' id_anterior %}" style="background-color: #691C32; border: none;">Siguiente</a>
{% endif %}
</form>
</div>
</section>
{% endblock %}
Note: variable names are in spanish
Note: the fieds that matter are marca, modelo, submodelo, numero_serie

Related

Django - Deleting using modal: show and delete only the first item from the table

Please help me understand the problem. I try to use the modal to delete each line separately but instead of displaying and deleting my actual line, it always displays and deletes the first line in the table. Where am I wrong with the code? Below my settings. Thank you very much.
models.py
class Post(models.Model):
class DisplayOnlyPublicat(models.Manager):
def get_queryset(self):
return super().get_queryset() .filter(status='publicat')
options =(
('draft', 'nepublicat'),
('publicat', 'publicat')
)
title = models.CharField(max_length=250)
poster = models.ImageField ( upload_to ='posts/', default='posts/poster_articole_pp.jpg')
category = models.ForeignKey(Category, on_delete=models.SET_DEFAULT, default=1)
slug = models.SlugField(max_length=250, unique_for_date='publish')
publish = models.DateTimeField(default=timezone.now)
author = models.ForeignKey (User, null=True, on_delete=models.SET_NULL, related_name='profipedia_posts')
short_content = models.TextField(null=True)
# content = models.TextField()
# content = RichTextField()
content = RichTextUploadingField(external_plugin_resources=[( 'emojione', '/static/vendor/ckeditor_plugins/emojione/' , 'plugin.js', )],)
status = models.CharField(max_length=10, choices=options, default='draft')
id = models.UUIDField(default=uuid.uuid4, unique=True, primary_key=True, editable=False)
objects = models.Manager() #denumire initiala
dop = DisplayOnlyPublicat() # denumire custom
def get_absolute_url(self):
return reverse('posts:articol', args=[self.slug])
# sa deschida articolul pe baza de denumire(slug) din sectiunea admin indiferent de statusul articolului (publicat/nepublicat)
# def get_absolute_url_adm(self):
# return reverse('posts:articolAdm', args=[self.slug])
class Meta:
ordering = ('-publish',)
def __str__(self):
return self.title
views.py
def delete_articol(request, articol_id):
post = Post.objects.get(pk=articol_id)
post.delete()
messages.success(request, "Articolul a fost sters!")
return redirect('posts:articoleAdm')
urls.py
urlpatterns = [
path('', views.articole, name='articole'),
path('articole-admin/', views.articoleAdm, name='articoleAdm'),
path('<slug:post>/', views.articol, name='articol'),
path('articole-admin/creare-articol/', views.creareArticol, name='creareArticol'),
path('articole-admin/<pk>/', views.articolAdm, name='articolAdm'),
path('modificare-articol/<str:pk>/', views.modificareArticol, name='modificareArticol'),
path('sterge-articol/<articol_id>/', views.delete_articol, name='stergeArticol'),
path('filtru/<category>', views.CatListView.as_view(), name='categorieArticol'),
]
html template
<table class="data-table data-table-pagination data-table-standard responsive nowrap hover"
id="datatableHover" data-order='[[ 0, "desc" ]]'>
<thead>
<tr>
<th class="text-muted text-small text-uppercase">Poster</th>
<th class="text-muted text-small text-uppercase">Autor</th>
<th class="text-muted text-small text-uppercase">Titlu</th>
<th class="text-muted text-small text-uppercase">Status</th>
<th class="text-muted text-small text-uppercase">Categorie</th>
<th class="text-muted text-small text-uppercase">Data</th>
<th class="empty"> </th>
<th class="empty"> </th>
<th class="empty"> </th>
</tr>
</thead>
<tbody>
{% for post in posts %}
<tr>
<td class="p-1"><img width="100" height="100%" class="rounded" src="{{post.poster.url}}"
alt=""></td>
<td>{{post.author}}</td>
<td><a class="list-item-heading body" href="{{post.id}}">{{post.title}}</a></td>
{% if post.status == "draft" %}
<td><span class="badge rounded-pill bg-muted">{{post.status}}</span></td>
{% else %}
<td><span class="badge bg-outline-success">{{post.status}}</span></td>
{% endif %}
{% if post.category.name == "nealocata" %}
<td><span class="badge rounded-pill bg-muted">{{ post.category }}</span></td>
{% else %}
<td><span class="badge bg-outline-muted">{{ post.category }}</span></td>
{% endif %}
<td> <small>{{post.publish|date:"d.m.Y - H:m:s"}}</small></td>
<td> <button class="btn btn-icon btn-icon-only btn-foreground-alternate edit-datatable " data-bs-toggle="tooltip" data-bs-placement="top" title="modificare articol" type="button" data-bs-delay="0"><i data-acorn-icon="eye"></i></button></td>
<td> <button class="btn btn-icon btn-icon-only btn-foreground-alternate edit-datatable " data-bs-toggle="tooltip" data-bs-placement="top" title="modificare articol" type="button" data-bs-delay="0"><i data-acorn-icon="edit"></i></button></td>
<td><button type="button" class="btn btn-icon btn-icon-only btn-foreground-alternate" data-bs-toggle="modal" data-bs-target="#deletePostPPP"><i data-acorn-icon="bin"></i></button></td>
</tr>
<!-- delete modal-->
<div class="modal fade" id="deletePostPPP" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Modal title</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"
aria-label="Close"></button>
</div>
<div class="modal-body">Sigur vrei să ștergi articolul <br>
<strong>"{{post.title}}"</strong>?</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary"
data-bs-dismiss="modal">Close</button>
<a href="{% url 'posts:stergeArticol' post.id %}"><button type="submit"
class="btn btn-primary">Understood</button></a>
</div>
</div>
</div>
</div>
{% endfor %}
</tbody>
</table>
Your delete buttons all refer to the same modal. The issue is that all the modals you generate have the same id. When referring to that id, the first modal will be shown.
What you should do instead is give each modal a separate id, containing e.g. the post id. Then call that specific modal in your delete button.
Your delete button:
<td><button type="button" class="btn btn-icon btn-icon-only btn-foreground-alternate" data-bs-toggle="modal" data-bs-target="#deletePostPPP-{{post.id}}"><i data-acorn-icon="bin"></i></button></td>
Your modal:
<!-- delete modal -->
<div class="modal fade" id="deletePostPPP-{{post.id}}" tabindex="-1" role="dialog" aria-hidden="true">

Django passing the value of the form in Django-forms

I have 2 models WorkoutCategory and workout with a ForeignKey with workout_Category in catig
in my template i have a collapsed div "WorkoutCategory" include a collapse form "to save in workoutmodel
the question is how I should pass the catig_id if it's not included in the form
below screenshot to simplify my idea
collapsed div for woroutcategory and the form
models:
from django.db import models
# Create your models here.
class WorkoutCategory(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Workout(models.Model):
catig = models.ForeignKey(WorkoutCategory,null=True, on_delete=models.CASCADE)
workout_name = models.CharField(max_length=250)
video_link = models.CharField(max_length=300)
def __str__(self):
return self.workout_name
the Form:
from django.forms import *
from .models import *
from django import forms
class CreateWorkoutForm(ModelForm):
class Meta:
model = Workout
exclude = ['catig']
widgets = {
'workout_name' : forms.TextInput(attrs={'class':'form-control','placeholder':'Workout Name'}),
'video_link' : forms.URLInput(attrs={'class':'form-control','placeholder':'https://www.youtube.com/ ...'}),
}
the Template:
{% for catg in allcetgs %}
<br>
<div class="card-header" data-toggle="collapse" href="#multiCollapseExample{{catg.id}}" role="button" aria- expanded="false" aria-controls="multiCollapseExample{{catg.id}}">
{{catg.name}}</div>
<div class="row">
<div class="col">
<div class="collapse multi-collapse" id="multiCollapseExample{{catg.id}}">
<div class="col">
<br>
<div class="btn btn-success" data-toggle="collapse" href="#addingworkout{{catg.id}}" role="button" aria-expanded="false" aria-controls="addingworkout{{catg.id}}" style="float: right;">add workout</div>
<br> <br>
<div class="collapse multi-collapse" id="addingworkout{{catg.id}}" >
<form method="POST" action="">
{% csrf_token %}
<div class="form-row">
<div class="col">
{{workoutForm.workout_name}}
</div>
<div class="col">
{{workoutForm.video_link}}
</div>
<button type="submit" class="btn btn-primary">Save</button>
</div>
</form>
</div>
</div>
<br>
<table class="table">
<thead>
<tr>
<th scope="col">Workout Name</th>
<th scope="col">Youtube Link</th>
</tr>
</thead>
<tbody>
{% for wkout in catg.workout_set.all %}
<tr>
<td>{{wkout.workout_name}}</td>
<td>check video</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
I don't want the user it set the catig_id since it's already the parent div of the form. how should I pass that catig_id value
# You don't need to exclude the catig field in your form
class CreateWorkoutForm(ModelForm):
class Meta:
model = Workout
widgets = {
'workout_name' : forms.TextInput(attrs={'class':'form-control','placeholder':'Workout Name'}),
'video_link' : forms.URLInput(attrs={'class':'form-control','placeholder':'https://www.youtube.com/ ...'}),
}
# you can have the value of catig_id in the hidden input
<div class="collapse multi-collapse" id="addingworkout{{catg.id}}" value="{{catg.id}}">
<form id="addingworkout">
<div class="form-row">
<input type="hidden" name="catig" value="{{catg.id}}">
<div class="col">
{{workoutForm.workout_name}}
</div>
<div class="col">
{{workoutForm.video_link}}
</div>
<button type="submit" class="btn btn-primary">Save</button>
</div>
</form>
</div>

Issue with CreateView ,object not created in model on submit

I have issue might missed something , i have created CreateView view for submitting objects in db , all seems to ok , but when i try to submit i don't get anything happen no error at all except
"POST /create_task/ HTTP/1.1" 200 12972 ,
MY code goes as follows , please advice
Thanks
models.py
class MainTask(models.Model):
task_title = models.CharField(max_length=200)
global_task_info = models.TextField(max_length=500,default=None)
complete = models.BooleanField(default=False)
overall_precent_complete = models.PositiveIntegerField(default=0)
created_at = models.DateTimeField(default=datetime.datetime.now())
updated_at = models.DateTimeField(default=datetime.datetime.now())
due_date = models.DateTimeField(default=datetime.datetime.now())
task_location = models.CharField(max_length=400, blank=True, null=True)
global_task_assign = models.ForeignKey(UserProfile, on_delete=models.CASCADE, related_name="global_task_assign",default=1)
TASK_STATUS_CHOICES = [
('ST', 'STARTED'),
('NS', 'NOT STARTED'),
('IP', 'IN PROGRESS'),
('PA', 'PAUSED'),
('CO', 'COMPLETED'),
]
task_status = models.CharField(max_length=2,choices=TASK_STATUS_CHOICES,default='NOT STARTED')
def __str__(self):
return self.task_title
forms.py
class TaskCraetionForm(forms.ModelForm):
TASK_STATUS_CHOICES = [
('ST', 'STARTED'),
('NS', 'NOT STARTED'),
('IP', 'IN PROGRESS'),
('PA', 'PAUSED'),
('CO', 'COMPLETED'),
]
task_title = forms.CharField(max_length=200, widget=forms.TextInput(attrs={'class':'form-control','placeholder':'Task Title'}))
global_task_info = forms.CharField(max_length=500, widget=forms.Textarea(attrs={'class':'form-control','placeholder':'Task Description'}))
due_date = forms.DateTimeField(widget=forms.DateTimeInput(attrs={
'class': 'form-control',
'id': 'picker'
}))
global_task_assign = forms.ModelChoiceField(queryset= UserProfile.objects.all(), widget=forms.Select(attrs={'class':'form-control'} ))
task_status = forms.ChoiceField(label='', choices=TASK_STATUS_CHOICES, widget=forms.Select(attrs={'class':'form-control'}))
class Meta:
model = MainTask
fields = ['task_title',
'global_task_info',
'due_date',
'global_task_assign',
'task_status',
]
views.py
class CreatTaskView(CreateView):
model = MainTask
template_name = "create_newtask.html"
form_class = TaskCraetionForm
success_url = None
def form_valid(self, form):
f = form.save(commit=False)
f.save()
return super(CreatTaskView, self).form_valid(form)
Thank you very much Alasdair you're comment gave me the direction and more added the following to my HTML template shown below and found out i have issue with my datetime picker format needed to added the following
Thanks
INPUTֹTIMEֹFORMATS = [
'%Y/%m/%d %H:%M']
due_date = forms.DateTimeField(input_formats=INPUTֹTIMEֹFORMATS, widget=forms.DateTimeInput(attrs={
'class': 'form-control',
'id': 'picker'
}))
html temaplate
<form action="" method="POST">
<h3 class="mt-3 text-left">Create New Task</h3>
<hr>
<p class="text-muted text-left">Creat New Itom task</p>
{% csrf_token %}
{% if form.errors %}
<!-- Error messaging -->
<div id="errors">
<div class="inner">
<p>There were some errors in the information you entered. Please correct the following:</p>
<ul>
{% for field in form %}
{% if field.errors %}<li>{{ field.label }}: {{ field.errors|striptags }}</li>{% endif %}
{% endfor %}
</ul>
</div>
</div>
<!-- /Error messaging -->
{% endif %}
<div class="input-group mt-3 mb-3 mr-auto">
<div class="input-group-prepend">
<span class="input-group-text" id="basic-addon1"><i class="fas fa-book-medical"></i></span>
</div>
{{ form.task_title}}
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fas fa-pen"></i></span>
</div>
{{form.global_task_info}}
</div>
<!---date time picker-->
<h6 class="text-left">Task Due Date</h6>
<div class="input-group date mb-3 col-3">
<div class="input-group-append">
<div class="input-group-text"><i class="fa fa-calendar"></i></div>
</div>
{{ form.due_date }}
</div>
<!--end of date time picker-->
<!---user assign-->
<h6 class="text-left">Assign Task to IT member</h6>
<div class="input-group mb-3 mt-3 col-8">
<div class="input-group-prepend">
<div class="input-group-text"><i class="fas fa-user-tie"></i></div>
{{form.global_task_assign}}
</div>
</div>
<!--End Of User Assign-->
<h6 class="text-left">Set Task Status</h6>
<div class="input-group mb-3 mt-3 col-4">
<div class="input-group-prepend">
<div class="input-group-text"><i class="far fa-caret-square-right"></i></div>
</div>
{{form.task_status}}
</div>
<div class="col text-left">
<button type="submit" value="Save" class="btn btn-primary btn-lg text-white mt-2"><span><i class="fas fa-database"></i></span> Create Task</button>
</div>
</form>
</div>
</div>

How to count objects in django

Thank you all for always sharing your knowledge here.
I have an issue with counting an object in Django. I am currently learning and working on a basic HR system and already have my views, models, et al set up. I plan to have an interface whereby I can print out employees count based on gender. The one I currently have set up is increasing the counts for both male and female any time I create a new employee. Please how do I correct this anomaly?
views.py
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from django.shortcuts import render
from django_tables2 import RequestConfig
from django_tables2.export import TableExport
from .models import Employee
from .models import EmployeeFilter
from .tables import EmployeeTable
#login_required()
def employees(request):
filter = EmployeeFilter(request.GET, queryset=Employee.objects.all())
table = EmployeeTable(filter.qs)
RequestConfig(request, paginate={"per_page": 15}).configure(table)
count = Employee.objects.all().count()
male_count = Employee.objects.filter(gender__contains='Male').count()
female_count = Employee.objects.filter(gender__contains='Female').count()
user_count = User.objects.all().count()
export_format = request.GET.get("_export", None)
if TableExport.is_valid_format(export_format):
exporter = TableExport(export_format, table)
return exporter.response("table.{}".format("csv", "xlsx"))
return render(request, "employees/employees.html", {
"table": table,
"filter": filter,
"count": count,
"male_count": male_count,
"female_count": female_count,
"user_count": user_count,
})
template.html
{% extends "employees/base.html" %}
{% load render_table from django_tables2 %}
{% load django_tables2 %}
{% load querystring from django_tables2 %}
{% block content %}
<!--Data overview-->
<div class="container data overview">
<div class="row">
<div class="col-md-3">
<div class="container-fluid bg-warning data-ov-container">
<div class="row">
<div class="col-8">
<h6 class="data-heading font-weight-bold">Total Employees</h6>
<p class="data-text ">{{ count }}</p>
</div>
<div class="col-4">
<i class="fas fa-users data-icon"></i>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div class="container-fluid bg-dark data-ov-container">
<div class="row">
<div class="col-9">
<h6 class="data-heading text-white font-weight-bold">Male Employees</h6>
<p class="data-text text-white">{{ male_count }}</p>
</div>
<div class="col-3">
<i class="fas fa-male data-icon text-white"></i>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div class="container-fluid bg-danger data-ov-container">
<div class="row">
<div class="col-9">
<h6 class="data-heading text-white font-weight-bold">Female Employees</h6>
<p class="data-text text-white">{{ female_count }}</p>
</div>
<div class="col-3">
<i class="fas fa-female data-icon text-white"></i>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div class="container-fluid bg-secondary data-ov-container">
<div class="row">
<div class="col-8">
<h6 class="data-heading text-white font-weight-bold">Active Users</h6>
<p class="data-text text-white">{{ user_count }}</p>
</div>
<div class="col-4">
<i class="fas fa-users-cog data-icon text-white"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<!--Employees data-->
<div class="filter-container container-fluid">
<div class="row">
<div class="col-md-9">
<!--filter form-->
<form action="" class="form form-inline employee-filter-form" method="get">
<legend class="mb-2">Filter employee records</legend>
{{ form.non_field_errors }}
<div class="fieldWrapper">
{{ filter.form.first_name.errors }}
{{ filter.form.first_name }}
</div>
<div class="fieldWrapper">
{{ filter.form.last_name.errors }}
{{ filter.form.last_name }}
</div>
<button aria-expanded="false" aria-haspopup="true"
class="ml-2 btn btn-danger filter-btn" type="submit">
Filter
</button>
</form>
</div>
<div class="col-md-3 download-btn-col">
<button aria-expanded="false" aria-haspopup="true"
class="mr-3 btn btn-success" type="submit">
<i class="fas fa-upload"></i> Import
</button>
<div class="btn-group download-btn">
<button aria-expanded="false" aria-haspopup="true"
class="btn btn-warning dropdown-toggle"
data-toggle="dropdown" type="button">
<i class="fas fa-file-export"></i> Export
</button>
<div class="dropdown-menu">
<a class="dropdown-item" href="{% querystring '_export'='csv' %}">csv</a>
<a class="dropdown-item" href="{% querystring '_export'='xlsx' %}">xlsx</a>
</div>
</div>
</div>
</div>
</div>
<!-- data rendered here -->
{% render_table table 'django_tables2/bootstrap.html' %}
<!-- data rendered here -->
{% endblock content %}
models.py
...
GENDER_CHOICES = (
('FEMALE', 'Female'),
('MALE', 'Male'),
("DWTS" "Don't want to say"),
)
...
#python_2_unicode_compatible
class Employee(models.Model):
# basic information of employee
first_name = models.CharField(_('first name'), max_length=40)
last_name = models.CharField(_('last name'), max_length=40)
emp_photo = models.ImageField(_('passport'))
date_of_birth = models.DateField(_('birthday'))
gender = models.CharField(_('gender'), max_length=15, choices=GENDER_CHOICES, default=['MALE', 'Male'])
house_address = models.CharField(_('house address'), max_length=100)
city_of_residence = models.CharField(_('city'), max_length=100)
state_of_residence = models.CharField(_('state'), max_length=100, choices=NIGERIAN_STATE_CHOICES)
country_of_residence = models.CharField(_('country'), max_length=100, choices=COUNTRY_CHOICES,
default=[156, 'Nigeria'])
state_of_origin = models.CharField(_('state of origin'), max_length=100, choices=NIGERIAN_STATE_CHOICES)
class Meta:
verbose_name = _('Employee')
verbose_name_plural = _('Employees')
def __str__(self):
return "{} {}".format(self.first_name, self.last_name)
#python_2_unicode_compatible
class EmployeeFilter(django_filters.FilterSet):
first_name = django_filters.CharFilter(lookup_expr='iexact', widget=TextInput(
attrs={'placeholder': 'First name', 'class': 'input_search'}))
last_name = django_filters.CharFilter(lookup_expr='iexact',
widget=TextInput(attrs={'placeholder': 'Last name', 'class': 'input_search'}))
class Meta:
model = Employee
fields = ["first_name", "last_name", ]
I think you need to remove contains from your filter:
male_count = Employee.objects.filter(gender='Male').count()
female_count = Employee.objects.filter(gender='Female').count()
Or make a single request:
male_femail_count = Employee.objects.values('gender').annotate(count=Count('id'))
# result
# [{'gender': 'Male', 'count': 2}, {'gender': 'Female', 'count': 3}]

Django 2.2.5 product not displaying in shopping cart

I am creating a e-commerce site using django 2.2.5. I've been following a tutorial on udemy where the instructor is moving at a rapid pace and he's using an older version of django i am continuously trying to pause just to ensure my code is correctly (it's AWFUL). I am now creating a shopping cart. The price is updating correctly but the product(s) price and description are not displaying. I've back tracked checked all the videos leading up to this part of the project but i can't seem to find what I've done incorrectly, so I've decided to come here for a second / third set of eyes that maybe able to see why the product(s) price and description are not displaying.
cart (cart.html): I have a forloop.counter that is looping through the products and is suppose to display the price and description of products added to the cart.
{% extends 'base.html' %}
{% block content %}
{% load staticfiles %}
<div class="pb-5">
<div class="container">
<div class="row">
<div class="col-lg-12 p-5 bg-white rounded shadow-sm mb-5">
<!-- Shopping cart table -->
<div class="table-responsive">
{% if cart.product.exists %}
<table class="table">
<thead>
<tr>
<th scope="col" class="border-0 bg-light">
<div class="p-2 px-3 text-uppercase">Product</div>
</th>
<th scope="col" class="border-0 bg-light">
<div class="py-2 text-uppercase">Price</div>
</th>
<th scope="col" class="border-0 bg-light">
<div class="py-2 text-uppercase">Quantity</div>
</th>
<th scope="col" class="border-0 bg-light">
<div class="py-2 text-uppercase">Remove</div>
</th>
</tr>
</thead>
<tbody>
{% for product in cart.products.all %}
<tr>
<th scope="row" class="border-0">{{ forloop.counter }}
<div class="p-2">
<img src="{{product.image}}" alt="" width="70" class="img-fluid rounded shadow-sm">
<div class="ml-3 d-inline-block align-middle">
<h5 class="mb-0"> {{ product.name }}</h5><span class="text-muted font-weight-normal font-italic d-block">Category: Watches</span>
</div>
</div>
</th>
<td class="border-0 align-middle"><strong>{{product.price}}</strong></td>
<td class="border-0 align-middle"><strong>3</strong></td>
<td class="border-0 align-middle"><i class="fa fa-trash"></i></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<p class="lead">Cart is empty</p>
{% endif %}
<!-- End -->
</div>
</div>
<div class="row py-5 p-4 bg-white rounded shadow-sm">
<div class="col-lg-6">
<div class="bg-light rounded-pill px-4 py-3 text-uppercase font-weight-bold">Coupon code</div>
<div class="p-4">
<p class="font-italic mb-4">If you have a coupon code, please enter it in the box below</p>
<div class="input-group mb-4 border rounded-pill p-2">
<input type="text" placeholder="Apply coupon" aria-describedby="button-addon3" class="form-control border-0">
<div class="input-group-append border-0">
<button id="button-addon3" type="button" class="btn btn-dark px-4 rounded-pill"><i class="fa fa-gift mr-2"></i>Apply coupon</button>
</div>
</div>
</div>
<div class="bg-light rounded-pill px-4 py-3 text-uppercase font-weight-bold">Instructions for seller</div>
<div class="p-4">
<p class="font-italic mb-4">If you have some information for the seller you can leave them in the box below</p>
<textarea name="" cols="30" rows="2" class="form-control"></textarea>
</div>
</div>
<div class="col-lg-6">
<div class="bg-light rounded-pill px-4 py-3 text-uppercase font-weight-bold">Order summary </div>
<div class="p-4">
<p class="font-italic mb-4">Shipping and additional costs are calculated based on values you have entered.</p>
<ul class="list-unstyled mb-4">
<li class="d-flex justify-content-between py-3 border-bottom"><strong class="text-muted">Order Subtotal </strong><strong>{{ cart.subtotal }}</strong></li>
<li class="d-flex justify-content-between py-3 border-bottom"><strong class="text-muted">Shipping and handling</strong><strong>$10.00</strong></li>
<li class="d-flex justify-content-between py-3 border-bottom"><strong class="text-muted">Tax</strong><strong>$0.00</strong></li>
<li class="d-flex justify-content-between py-3 border-bottom"><strong class="text-muted">Total</strong>
<h5 class="font-weight-bold">{{ cart.total }}</h5>
</li>
</ul>Proceed to checkout
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
cart (cart/models.py):
from django.conf import settings
from django.db import models
from django.db.models.signals import pre_save, post_save, m2m_changed
from products.models import Product
User = settings.AUTH_USER_MODEL
class CartManager(models.Manager):
def new_or_get(self, request):
cart_id = request.session.get("cart_id", None)
qs = self.get_queryset().filter(id=cart_id)
if qs.count() == 1:
new_obj = False
cart_obj = qs.first()
if request.user.is_authenticated and cart_obj.user is None:
cart_obj.user = request.user
cart_obj.save()
else:
cart_obj = Cart.objects.new(user=request.user)
new_obj = True
request.session['cart_id'] = cart_obj.id
return cart_obj, new_obj
def new(self, user=None):
user_obj = None
if user is not None:
if user.is_authenticated:
user_obj = user
return self.model.objects.create(user=user_obj)
class Cart(models.Model):
user = models.ForeignKey(User, null=True, blank=True, on_delete=True)
products = models.ManyToManyField(Product, blank=True)
subtotal = models.DecimalField(default=0.00, max_digits=19, decimal_places=2)
total = models.DecimalField(default=0.00, max_digits=19, decimal_places=2)
updated = models.DateTimeField(auto_now_add=True)
timestamp = models.DateTimeField(auto_now_add=True)
objects = CartManager()
def __str__(self):
return str(self.id)
def m2m_changed_cart_receiver(sender, instance, action, *args, **kwargs):
if action == 'post_add' or action == 'post_remove' or action == 'post_clear':
products = instance.products.all()
total = 0
for x in products:
total += x.price
if instance.subtotal != total:
instance.subtotal = total
instance.save()
m2m_changed.connect(m2m_changed_cart_receiver, sender=Cart.products.through)
def pre_save_cart_receiver(sender, instance, *args, **kwargs):
if instance.subtotal > 0:
instance.total = instance.subtotal + 6
else:
instance.total = 0.00
pre_save.connect(pre_save_cart_receiver, sender=Cart)
(cart/views.py):
from django.shortcuts import render, redirect
from products.models import Product
from .models import Cart
def cart_home(request):
template = "carts/cart.html",
cart_obj, new_obj = Cart.objects.new_or_get(request)
return render(request, template, {"cart": cart_obj})
def cart_update(request):
product_id = request.POST.get('product_id')
if product_id is not None:
product_obj = Product.objects.get(id=product_id)
cart_obj, new_obj = Cart.objects.new_or_get(request)
if product_obj in cart_obj.products.all():
cart_obj.products.remove(product_obj)
else:
cart_obj.products.add(product_obj)
return redirect("cart:home")
Products View (products/views.py):
class ProductDetailSlugView(DetailView):
queryset = Product.objects.all()
template_name = "products/detail.html"
def get_context_data(self, *args, **kwargs):
context = super(ProductDetailSlugView, self).get_context_data(*args, **kwargs)
cart_obj, new_obj = Cart.objects.new_or_get(self.request)
context['cart'] = cart_obj
return context
def get_object(self, *args, **kwargs):
request = self.request
slug = self.kwargs.get('slug')
try:
instance = Product.objects.get(slug=slug)
except Product.DoesNotExist:
raise Http404("Not Found")
except Product.MultipleObjectsReturned:
qs = Product.objects.filter(slug=slug)
instance = qs.first()
except:
raise Http404("hmmm can't seem to find product")
return instance
in cart.html I changed
{% if cart.product.exists %}
to
{% if cart.products.exists %}