How can i display count of each column in django - django

Display
I would like to count the number of students for each subjects but currently it only displays the number of students for one subject. it only counts the number of student for one subject but i would like to count the number of students in each subject
Added the models.py. Ps still new to django
views.py
class SubjectView(TemplateView):
template_name='subjects.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
username=self.request.user.id
#filter subject taught by lecturer
classdets=ClassDetail.objects.all().filter(teacher=username).values_list('subject_id')
print(classdets)
#filters all subjects from the class details
subj=Subject.objects.filter(id__in=classdets)
print(subj)
#counts number of students
subjID=Subject.objects.values('id')
num_student=ClassDetail.objects.filter(id__in=subjID).count
print(num_student)
context['subjects'] = subj
context['no_students'] = num_student
return context
template
{% extends "base.html" %}
{% load static %}
{% block title %}Subjects{% endblock title %}
{% block sidenavbar %}
{% include 'partials/sidenavbar.html' %}
{% endblock %}
{% block navbar %}
{% include 'partials/navbar.html' %}
{% endblock %}
{% block subject %}
<div class="container-fluid">
<div class="col">
<div class="card bg-transparent">
<!-- Card header -->
<div>
<div class="card-header bg-transparent border-0">
<h3 class="mb-0" style="text-transform: uppercase">Current Subjects</h3>
{% comment %} View Students {% endcomment %}
</div>
</div>
<!-- Translucent table -->
<div class="table-responsive">
<table class="table align-items-center table-flush" id="datatable-buttons">
<thead class="thead-light">
<tr>
<th>Subject Name</th>
<th>Subject Code</th>
<th>Number of Students</th>
{% comment %} <th>Generate Attendance Code</th> {% endcomment %}
</tr>
</thead>
{% if user.is_authenticated %}
{% for subject in subjects %}
<tbody class="list" style="text-transform: capitalize">
<tr>
<th scope="row">
<div class="media align-items-center">
<a href="#" class="avatar rounded-circle mr-3">
{% if subject.thumbnail %}
<img alt="Logo" src="{{subject.thumbnail.url}}" />
{% endif %}
</a>
<div class="media-body">
<span class="name mb-0 text-sm">{{subject}}</span>
</div>
</div>
</th>
<td class="budget">{{subject.code}}</td>
<td>
<div class="d-flex align-items-center">
<span class="completion mr-2">{{no_students}}</span>
</div>
</td>
<td>
{% comment %}
<div class="d-flex align-items-center">
<span class="completion mr-2">{{attendace_code}}</span>
</div>
{% endcomment %}
</td>
</tr>
</tbody>
{% endfor %}
{% endif %}
</table>
</div>
</div>
</div>
</div>
{% endblock %}
models
def get_thumbnail(instance, filename):
path = f"static/assets/img/custom/{filename}"
return path
class Subject(models.Model):
code=models.CharField(max_length=8,unique=True,default="")
name=models.CharField(max_length=100,unique=True)
thumbnail=models.ImageField(blank=True,null=True,upload_to=get_thumbnail)
def __str__(self):
return f'{self.name}'
class Meta:
unique_together = ('name', 'code')
class ClassDetail(models.Model):
teacher=models.ForeignKey(UserProfile,on_delete=models.PROTECT)
subject=models.ForeignKey(Subject, on_delete=models.PROTECT, default="")
student=models.ManyToManyField(UserProfile,related_name="student")
def __str__(self):
return f'{self.subject}'
class Meta:
unique_together = ('teacher', 'subject')
userprofile
class UserProfile(AbstractUser):
ROLE_LECTURER = 'lecturer'
ROLE_STUDENT = 'student'
ROLE_ADMIN = 'admin'
ROLE_CHOICES = (
(ROLE_LECTURER, _('Lecturer')),
(ROLE_STUDENT, _('Student')),
(ROLE_ADMIN, _('Admin')),
)
STATUS_ACTIVE = 'active'
STATUS_INACTIVE = 'inactive'
STATUS_SUSPENDED = 'suspended'
STATUS_EXPIRED = 'expired'
STATUS_CHOICES = (
(STATUS_ACTIVE, _('Active')),
(STATUS_INACTIVE, _('Inactive')),
(STATUS_SUSPENDED, _('Suspended')),
(STATUS_EXPIRED, _("Expired")),
)
username = models.CharField(max_length=11, unique=True, verbose_name="Relevant ID")
status = models.CharField(_('status'), max_length=50, choices=STATUS_CHOICES, default=STATUS_ACTIVE)
role = models.CharField(_('role'), max_length=50, choices=ROLE_CHOICES, default="")
def __str__(self):
return f'{self.username} ({self.first_name})'
USERNAME_FIELD = 'username'

num_student =subjID.classdetail_set.all().count()
print(num_student)

Related

Django how to display list users with some data in template

I want to display the list of users with some objects in 2 modelapps created.
these are the models.
first model:
class UserProfile(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE)
indirizzo = models.CharField(max_length=50)
citta = models.CharField(max_length=50)
paese = models.CharField(max_length=50)
ecap = models.CharField(max_length=4)
descrizione = models.CharField(max_length=100, default='')
image = models.ImageField(upload_to='profile_image', blank=True,null=True)
second model:
class Ore(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="ore",null=True,)
data = models.DateField(default=timezone.now)
oret = models.CharField(max_length=3,)
contrattiok = models.PositiveSmallIntegerField()
contrattiko = models.PositiveSmallIntegerField(default=0,)
nomecognome = models.CharField(max_length=100,blank=True)
my view:
def inizio(request):
users = User.objects.all()
return render (request, "base.html", {"users":users})
my template:
{% for users in users %}
<tbody>
<tr>
<td>
<img src="{{ users.userprofile.image.url }}"class="thumbnail">
<h4 class="small font-weight-bold">{{users}}</h4>
</td>
<td><h4 class="small font-weight-bold">{{users.last_name}}</h4></td>
<td class="text-center">
<h4 class="small font-weight-bold" class="btn btn-primary btn-circle">{{ users.ore.contrattiok }}</h4> <<<<<(does not work)
</td>
</tr>
{% endfor %}
I saw several problems in your templates.
1. It would be better to make different variable of users loop to increase readability code.
don't do this: {% for users in users %}
but instead: {% for user in users %}
so then you can use it with user instead of users inside loop like:
{{ user.last_name }}
2. your <tbody> inside forloop users, but theres no </tbody> right before the {% endfor %}.
But I suggest you to do not include <tbody> inside forloop.
Do this instead:
<tbody>
{% for user in users %}
<tr><td></td></tr>
{% endfor %}
</tbody>
since your foreign key is inside Ore model instead
(one to many relationship which means 1 user has many ores),
so you need to loop every ore on each user.
{% for user in users %}
{% for ore in user.ore.all %}
{{ ore.contrattiok }}
{% endfor %}
{% endfor %}
so the final result will be like this:
<tbody>
{% for user in users %}
<tr>
<td>
<img src="{{ user.userprofile.image.url }}" class="thumbnail">
<h4 class="small font-weight-bold">{{ user }}</h4>
</td>
<td><h4 class="small font-weight-bold">{{user.last_name}}</h4></td>
<td class="text-center">
{% for ore in user.ore.all %}
<h4 class="small font-weight-bold" class="btn btn-primary btn-circle">
{{ ore.contrattiok }}
</h4>
{% endfor %}
</td>
</tr>
{% endfor %}
</tbody>
EDITED
based on your comment, so you want to sum the total of contrattiok field?
if that so, you need to change your view using annotate
from django.db.models import Sum
users = User.objects.annotate(total_contrattiok=Sum('ore__contrattiok'))
then in your template:
{% for user in users %}
<td class="text-center">
<h4 class="small font-weight-bold" class="btn btn-primary btn-circle">
{{ user.total_contrattiok }}
</h4>
</td>
{% endfor %}

How to create a search function on a class-based list view?

I am trying to create a search function based on the title of my posts. Right now I am trying to implement this search using a filter but the list view is not rendering. I am unsure if I should implement a URL for my search function.
This is my model:
class Post(models.Model):
title = models.CharField(max_length=100)
image = models.ImageField(default = 'default0.jpg', upload_to='course_image/')
description = models.TextField()
price = models.DecimalField(decimal_places=2, max_digits=6)
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
feedback = models.ManyToManyField(Feedback)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk' : self.pk})
This is my class-based list view:
class PostListView(ListView):
model = Post
template_name = 'store/sub_home.html' # <app>/<model>_<viewtype>.html
context_object_name = 'posts'
ordering = ['date_posted']
paginate_by = 12
def get_queryset(self):
object_list = super(PostListView, self).get_queryset()
search = self.request.GET.get('q', None)
if search:
object_list = object_list.filter(title__icontains = title)
return object_list
This is my search bar:
<div id="search">
<form method='GET' action=''>
<input type="text" name='q' placeholder="">
<button id='search_holder'>
<img src="/static/store/search_icon.gif" id="search_icon">
</button>
</form>
</div>
This is my html that is rendering the posts:
{% extends "store/base.html" %}
{% block content %}
{% include "store/home_ext.html" %}
<div style="padding-top: 20px;" id="main" >
<section class="text-center mb-4">
<div class="row" id="random">
{% for post in posts %}
{% include "store/card.html" %}
{% endfor %}
</div>
<div class="row" id="subscription" style="display: none;">
{% if not subs %}
<h2>You have not subscribed to any course :/</h2>
{% endif %}
{% for post in subs %}
{% include "store/card.html" %}
{% endfor %}
</div>
<div class="row" id="content" style="display: none;">
{% if not mine %}
<h2>You have not published anything :/</h2>
{% endif %}
{% for post in mine %}
{% include "store/card.html" %}
{% endfor %}
</div>
</section>
{% include "store/pagination.html" %}
</div>
{% endblock content %}
This is my card.html:
{% load extra_filter %}
<div class="col-lg-3 col-md-6 mb-4">
<div id="course_card">
<div class="view overlay">
<img style="margin-left: -10px;" src="{{ post.image.url }}" alt="">
</div>
<div>
<div>
<strong>
{% if user.is_authenticated %}
<a class="title" href="{% url 'post-detail' post.id %}" >
{% else %}
<a class="title" href="{% url 'login' %}" >
{% endif %}
{% if post.title|length < 30 %}
<span>{{ post.title }}</span>
{% else %}
<span>{{ post.title|cut:27 }}</span>
{% endif %}
<span style="background-color: rgb(253, 98, 98);" class="badge badge-pill danger-color">NEW
</span>
</a>
</strong>
</div>
<div class="star-ratings-css">
<div class="star-ratings-css-top" style="width: {{ post.feedback|calc_rating }}%"><span>★</span><span>★</span><span>★</span><span>★</span><span>★</span></div>
<div class="star-ratings-css-bottom"><span>★</span><span>★</span><span>★</span><span>★</span><span>★</span></div>
</div>
<a href="{% url 'user-posts' post.author.username %}" class="author">
by {{ post.author }}
</a>
<div>
<strong style="text-align: right;" class="price">S${{ post.price }}
</strong>
</div>
<small class="date">
{{ post.date_posted|date:'d F y'}}
</small>
</div>
</div>
</div>
As Nalin Dobhal mentioned in comments, context_object_name should be posts not post. Because in template, you are iterating through posts context variable. Also, when using search functionality, the implementation should be like this:
class PostListView(ListView):
model = Post
template_name = 'store/sub_home.html' # /_.html
context_object_name = 'posts'
ordering = ['date_posted']
paginate_by = 12
def get_queryset(self, *args, **kwargs):
object_list = super(PostListView, self).get_queryset(*args, **kwargs)
search = self.request.GET.get('q', None)
if search:
object_list = object_list.filter(title__icontains = search)
return object_list
Because you are sending the search query through URL querystring(ie: url will look like /posts/?q=title in browser). I am using request.GET.get('q') to fetch those query string values, and use it to filter the queryset.

Why is my Class-based delete view not working?

My delete view is not working and the error message is:
Page not found (404) Request Method: GET.
I am trying to delete my uploaded file based on its primary key and so far, my url is able to link me correctly based on the pk.
This is my urls.py:
path('post/<int:post_id>/lesson_delete/<int:lesson_id>', LessonDeleteView.as_view(), name='lesson_delete'),
My views.py:
class LessonDeleteView(DeleteView):
model = Lesson
success_url = '../'
template_name = 'lesson_confirm_delete.html'
This is the html template that brings user to the delete view:
{% extends "store/base.html" %}
{% block content %}
<div id="main">
<table class="table mb-0">
<thead>
<tr>
<th>Title</th>
<th>Author</th>
<th>Download</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
{% for l in Lesson %}
<tr>
<td>
{% if l.file %}
{{ l.title }}
{% else %}
<h6>Not available</h6>
{% endif %}
</td>
<td>{{ l.post.author }}</td>
<td>{% if l.file %}
Download
{% else %}
<h6>Not available</h6>
{% endif %}
</td>
<td> <a class="btn btn-danger btn-sm mt-1 mb-1" href="{% url 'lesson_delete' lesson_id=l.id %}">Delete</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}
This is my html template for DeleteView:
{% extends "store/base.html" %}
{% block content %}
<div class="content-section" id="main">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Delete Lesson</legend>
<h2>Are you sure you want to delete the post "{{object.title}}"?
</h2>
</fieldset>
<span style="display:inline;">
<button class="btn btn-outline-danger" type="submit">Yes, Delete!
</button>
<a class="btn btn-outline-secondary" href ="">Cancel</a>
</span>
</form>
</div>
{% endblock content %}
This is my Lesson Model:
class Lesson(models.Model):
title = models.CharField(max_length=100)
file = models.FileField(upload_to="lesson/pdf")
date_posted = models.DateTimeField(default=timezone.now)
post = models.ForeignKey(Post, on_delete=models.CASCADE, null=False, blank=False)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('lesson_upload', kwargs={'pk': self.pk})
Is you template called 'lesson_confirm_delete.html'?
Also, for your success url, I have feeling you don't have a path '../'. It should the specific path you want it to go to.
(Sorry, I can't comment yet.)

Autocomplete through a selected external key (Django)

I have a query and I have 2 models, one called Detalleventa and Producto
class DetalleVenta(models.Model):
producto = models.ForeignKey(Producto,on_delete=models.CASCADE,verbose_name='Producto')
cantidad = models.IntegerField(verbose_name='Cantidad')
preciounit = models.DecimalField(decimal_places=2, max_digits=7, verbose_name='Precio unitario')
subtotal = models.DecimalField(decimal_places=2, max_digits=7, verbose_name='Subtotal')
venta = models.ForeignKey(Venta,on_delete=models.CASCADE, related_name='detalleventa', verbose_name='Venta')
def __str__(self):
return '{} - {}'.format(self.venta,self.producto)
class Producto(models.Model):
nombre = models.CharField(max_length=30,unique=True,verbose_name='Nombre de Producto:')
precio = models.DecimalField(decimal_places=2, max_digits=7, verbose_name='Precio de Producto:')
categoria = models.ForeignKey(Categoria,on_delete=models.CASCADE,verbose_name='Categoría:')
def __str__(self):
return self.nombre
And in my Detalle forms.py I have:
class DetalleForm(forms.ModelForm):
class Meta:
model = DetalleVenta
fields = [
'producto',
'cantidad',
'preciounit',
'subtotal',
]
labels = {
'producto':'Producto',
'cantidad':'Cantidad',
'preciounit':'Prec.Unit.',
'subtotal':'Subtotal',
}
widgets = {
'producto':forms.Select(attrs={'class':'form-control'}),
'cantidad':forms.NumberInput(attrs={'class':'form-control cantidad'}),
'preciounit':forms.NumberInput(attrs={'class':'form-control'}),
'subtotal':forms.NumberInput(attrs={'class':'form-control subtotal', 'readonly':True}),
}
DetalleFormSet = inlineformset_factory(Venta, DetalleVenta,
form=DetalleForm, extra=1)
As you can see in the details form, I have a priceunit field that refers to the price of the product that is in the product model and my question is: is there any way in my details template when selecting, for example, a product X ? ? (external key product) autocomplete its respective price in the input of preciounit?
This is my template:
{% extends 'base/base.html' %}
{% load static %}
{% block titulo%} Registrar venta {%endblock%}
{% block contenido %}
<div class="col-md-12">
<form method="post">{% csrf_token %}
<div class="col-md-4 form-group">
<label class="font-weight-bold" for="{{form.cliente.name}}">{{form.cliente.label}}</label>
{{form.cliente}}
</div>
<h4 class="text-left">Detalle de venta: </h4>
<div class="table-responsive-sm">
<table class="table" id="tablaDetalle">
{{ detalleformset.management_form }}
<thead class="thead-dark">
<th>Producto</th>
<th width="100px">Cantidad</th>
<th width="115px">Prec.Unit.</th>
<th width="115px">Subtotal</th>
<th>Acción</th>
</thead>
<tbody>
{% for form in detalleformset.forms %}
<tr class="formset_row">
{% for field in form.visible_fields %}
<td>
{# Include the hidden fields in the form #}
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{{ field.errors.as_ul }}
{{ field }}
</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="row justify-content-md-end">
<div class="col-md-2">
<label class="font-weight-bold" for="{{form.total.name}}">{{form.total.label}}</label>
{{form.total}}
</div>
</div>
<div class="form-group">
<label class="font-weight-bold" for="{{form.descripcion.name}}">{{form.descripcion.label}}</label>
{{form.descripcion}}
</div>
<div class="col-md-4 offset-md-4">
<button class="btn btn-block btn-lg btn-primary" type="submit"><span><i class="fa fa-shopping-cart"></i>
</span>Registrar venta</button>
</div>
</form>
</div>
{% endblock %}
As you know, it's for a small sales system and I have to get the price of the product. If there is a way to be able to do what has been proposed? or at least a clue to discover how to do it?

How to make a search engine for my comments

I am trying to make a search engine through the posted comments. The goal is to search the comments as easiest as possible. See below the architecture of the program:
views.py
class ComentarioListar (LoginRequiredMixin,ListView):
login_url='/'
redirect_field_name='redirigido'
model = Comentario
template_name = 'home/comentario_listar.html'
class busqueda (ListView):
model=Comentario
template_name='home/search.html'
def get_queryset(self):
qs=Comentario.objects.filter()
keywords=self.request.GET.get('q')
if keywords:
query=SearchQuery(keywords)
vector=SearchVector('titulo')
qs=qs.annotate(search=vector).filter(search=query)
qs=qs.annotate(rank=SearchRank(vector,query)).order_by('-rank')
return render(request, 'home/search.html', {'qs':qs} )
urls.py
urlpatterns = [
url(r'^listar$', ComentarioListar.as_view(), name="listar"),
url(r'^search$',busqueda, name="search"),]
models.py
class Comentario (models.Model):
titulo = models.CharField(max_length=50)
texto = models.CharField(max_length=200)
autor = models.ForeignKey (Perfil, null=True, blank=True, on_delete=models.CASCADE)
fecha_publicacion = models.DateTimeField(auto_now_add=True)
tag = models.ManyToManyField(Tags, blank=True)
def __str__(self):
return (self.titulo)
cometario_listar.html (where I have created the search button)
<form id="searchform" action="search/" method="GET" accept-charset="utf-8">
<button class="searchbutton" type="submit">
<i class="fa fa-search"></i>
</button>
<input class="searchfield" id="searchbox" name="q" type="text" placeholder="Search" id="busqueda">
</form>
{% endblock %}
search.html
{% extends 'base/base.html' %}
{% block content %}
<table class="table table-striped">
<thead class="thead-default">
<tr>
<td>Titulo</td>
<td>Descripcion</td>
<td>Autor</td>
<td>Fecha de publicación</td>
<td>Etiqueta</td>
</thead>
<tbody>
{% if qs %}
{% for comentario in object_list %}
<tr>
<td>{{comentario.titulo}}</td>
<td>{{comentario.texto}}</td>
<td>{{comentario.autor}}</td>
<td>{{comentario.fecha_publicacion}}</td>
{% for tag in comentario.tag.all %}
<td>{{ tag.nombre }}</td>
{% endfor %}
{% endfor %}
</tr>
{% else %}
<h1>No hay registros de comentarios</h1>
{% endif %}
</tbody>
</table>
The problem is that it does not work. 'http://127.0.0.1:8000/home/search/?q=nueva' appears correctly, but it does not make any filtering. Is it possible to use the same .html file (comentario_listar.html) to make the search?
thank you in advance for your help.