Django User Posts filter by year - python

In Django I needed user Posts filter by year, so I did the following in views:
Views:
from django.contrib.auth.models import User
from django.db.models import Count
from .models import Book
def about (request):
model = Book
context = {
'books': Book.objects.values('author')
.filter(date_posted__year=2019)
.annotate(total_books = Count('author'))
}
In the HTML
books.author.id
books.author
books.total_books
It worked, it shows the total but instead of printing de Author username, it prints the Author ID, and the author ID is blank.
Django Version 3.0.8
This is the complete HTML:
{% block content %}
<div class="container">
<div class="w-50">
<table class="table">
<thead class="thead-dark">
<tr>
<th scope="col">User ID</th>
<th scope="col">Username </th>
<th scope="col">Total Books</th>
</tr>
</thead>
{% for books in books %}
<tbody>
<tr>
<ul>
<td> {{ books.author }}</td>
<td> {{ books.author }} </td>
<td>{{ books.total_qcreports}}</td>
</ul>
</tr>
</tbody>
{% endfor %}
</table>
</div>
</div>
{% endblock content %}
Models:
class Book(models.Model):
title = models.CharField(max_length=100)
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.title
This is how it shows in browser:
enter image description here

context = {
'books': Book.objects.values('author','author__username')
.filter(date_posted__year=2019)
.annotate(total_books = Count('author'))
}
HTML Template
{{book.author}}
{{book.author__username}}
{{book.total_book}}

Related

How do you display model attribute in a table within am html file?

I have a project and a task model and I want to make a table in a detail html that displays the tasks in the project.
I've tried doing
<table>
<tr>
<th>Name</th>
<th>Assignee</th>
<th>Start Date</th>
<th>Due Date</th>
<th>Is compeleted</th>
</tr>
<tr>
<td>{{ task.name }} </td>
<td>{{ task.assignee }}</td>
<td>{{ task.start_date }}</td>
<td>{{ task.due_date }}</td>
<td>{{ task.is_completed }}</d>
</tr>
</table>
but it just shows the table headers and not its content
here is my task model
from django.db import models
from django.conf import settings
from django.urls import reverse
# Create your models here.
class Task(models.Model):
name = models.CharField(max_length=200)
start_date = models.DateTimeField()
due_date = models.DateTimeField()
is_completed = models.BooleanField(default=False)
project = models.ForeignKey(
"projects.Project",
related_name="tasks",
on_delete=models.CASCADE,
)
assignee = models.ForeignKey(
settings.AUTH_USER_MODEL,
null=True,
related_name="tasks",
on_delete=models.SET_NULL,
)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse("show_my_tasks")
An answer to your previous question had something like:
{% for project in projects_list %}
...
{% if project.tasks.count > 0 %}
# Displaying the table in here with the project's task info...
{% else %}
<p> no tasks for this project </p>
{% endif %}
...
{% endfor %}
You should loop over all the project's tasks set within the table. For example:
# Within the true portion of the if statement...
{% if project.tasks.count > 0 %}
# Displaying the table in here with the project's task info...
<table>
<thead>
<tr>
<th>Name</th>
<th>Assignee</th>
<th>Start Date</th>
<th>Due Date</th>
<th>Is compeleted</th>
</tr>
</thead>
<tbody>
# The set of related tasks for the current project -> project.tasks.all
{% for task in project.tasks.all %}
<tr>
<td>{{ task.name }} </td>
<td>{{ task.assignee }}</td>
<td>{{ task.start_date }}</td>
<td>{{ task.due_date }}</td>
<td>{{ task.is_completed }}</d>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p> no tasks for this project </p>
{% endif %}

Django app not displaying data in template

im brand new to Django and attempting to make my first ECommerce site. I'm attempting to get a list of products from a .JSON file to display in my products.html template. The products are in place, as shown in the Django admin portal, productsis definied with in my views.py file and i've done loaddata but nothing comes through. I've added some screenshots and code below to further explain.
Views.py Code:
from django.shortcuts import render
from .models import Product
def all_products(request):
products = Product.objects.all()
context = {
'products': products,
}
return render(request, 'products/products.html', context)
products.html Template:
{% extends "base.html" %}
{% load static %}
{% block page_header %}
<div class="container header-container">
<div class="row">
<div class="col"></div>
</div>
</div>
{% endblock %}
{% block content %}
<div class="container">
<div class="row">
<div class="col">
{{ products }}
</div>
</div>
</div>
{% endblock %}
My folder structure is correct but I'll post it here just incase:
Any help would be great as i've been stuck with this for a while now. Thanks!
models.py:*
class Product(models.Model):
category = models.ForeignKey('category', null=True, blank=True, on_delete=models.SET_NULL)
sku = models.CharField(max_length=254, null=True, blank=True)
name = models.CharField(max_length=254)
description = models.TextField()
price = models.DecimalField(max_digits=6, decimal_places=2)
rating = models.DecimalField(max_digits=6, decimal_places=2, null=True, blank=True)
image_url = models.URLField(null=True, blank=True)
image = models.ImageField(null=True, blank=True)
def __str__(self):
return self.name
You need to iterate through the object you are passing to your template.
For example,
{% for product in products %}
<img src={{ product.src }} />
<h3>{{ product.title }}</h3>
<p>{{ product.desc }}</p>
{% endfor %}
You have done most of the thing right so far. One thing that causes the issue is the template didn't iterate all the products.
In the views.py, Product.objects.all() returns a query set which you can imagine it is a list that contains many product instances.
So when the products, which is Product.objects.all(), is passed to template, you will need to use a loop to iterate the instances inside the products.
I assume your product model contains the following three fields(you can replace them with the actual field inside your product model later in the example I provide).
name
description
qty
Now, in Django template, you can replace the {{ products }} with the following code.
<table>
<thead>
<tr>
<th scope="col" class="text-nowrap"><span>Product</span></th>
<th scope="col" class="text-nowrap"><span>Description</span></th>
<th scope="col" class="text-nowrap"><span>Qty</span></th>
</tr>
</thead>
<tbody>
{% for product in products %}
<tr>
<td><span>{{ product.name }}</span></td><!-- Replace the name with your actual field -->
<td><span>{{ product.desciption }}</span></td><!-- Replace the desciption with your actual field -->
<td><span>{{ product.qty }}</span></td><!-- Replace the qty with your actual field -->
</tr>
{% endfor %}
</tbody>
</table>
With the above example, the most important part is
{% for product in products %}
<tr>
<td><span>{{ product.name }}</span></td>
<td><span>{{ product.desciption }}</span></td>
<td><span>{{ product.qty }}</span></td>
</tr>
{% endfor %}
It is similar to the following python code.
for product in products:
print(product.name)
print(product.desciption)
print(product.qty)
And as a result, now the template should show the product on a table.

When displaying foreign key base Queryset on template

I have two models shown below
class Services(models.Model):
name = models.CharField(max_length=200, null=True)
price = models.FloatField(null=True)
service_sku = models.CharField(max_length=200, null=True)
class Order(models.Model):
customer = models.ForeignKey(Customer, null=True, on_delete = models.SET_NULL)
service = models.ForeignKey(Service, null=True, on_delete = models.SET_NULL)
I have created a function-based view based on the service model where I want to render a template displaying a list of field information from each instance from the service model.
See below for my views and template
views.py
def service_list(request):
service_list = Service.objects.all().order_by('service_sku')
context = {'service_list':service_list}
return render(request, 'accounts/service_list.html',context)
template
<div class="card card-body">
<table class="table">
<tr>
<th>SKU</th>
<th>Service Name</th>
<th>Number of Ordered</th>
</tr>
{% for i in service_list %}
<tr>
<td>{{i.service_sku}}</td>
<td>{{i.name}} </td>
<td></td>
</tr>
{% endfor %}
I want to display the number of orders of each instance, considering that the order model has a foreign key from the service model.
The query set would have to be like the below shown.
Order.objects.all().filter(service__id =3).count()
Problem is that I must specify which id of that model would be for that queryset to work.
I’ve tried to put the queryset format below within the template
{{Order.objects.all().filter(service__id=i.id).count()}
In the template it would look like how it does below
template
<div class="card card-body">
<table class="table">
<tr>
<th>SKU</th>
<th>Service Name</th>
<th>Number of Ordered</th>
</tr>
{% for i in service_list %}
<tr>
<td>{{i.service_sku}}</td>
<td>{{i.name}} </td>
<td>{{Order.objects.all().filter(service__id=i.id).count()}}</td>
</tr>
{% endfor %}
The above implementation does not work.
Which method is ideal for this situation?
You can not call methods (with parameters) in a Django template. The templates are deliberately restricted to prevent people from writing business logic in the templates.
You can .annotate(…) [Django-doc] the queryset to fetch the number of related Orders:
from django.db.models import Count
def service_list(request):
service_list = Service.objects.annotate(
norders=Count('order')
).order_by('service_sku')
context = {'service_list':service_list}
return render(request, 'accounts/service_list.html',context)
In the template you can then render this with:
{% for i in service_list %}
<tr>
<td>{{ i.service_sku }}</td>
<td>{{ i.name }} </td>
<td>{{ i.norders }}</td>
</tr>
{% endfor %}

Python Django tables with checkbox delete option

I am new to Django and currently trying to display a table with a checkbox which displays the list of records from the database and would have a delete button to delete multiple records using checkbox.
How to display a table with checkbox and delete button?
Appreciate your help!
Here is my code related to it:
models.py
class Customer(TimeStamp):
name = models.CharField(max_length=30, unique=True)
description = models.CharField(max_length=100,blank=True,help_text="Long-form name (optional)")
comments = models.TextField(blank=True)
class Meta:
ordering = ['-id']
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('App_CUS:customer_list')
views.py
class CustomerListView(ListView):
queryset = Customer.objects.order_by('id')
model = Customer
paginate_by = 10
context_object_name = 'customers'
template_name = 'App_CUS/customer_list.html'
customer_list.html
customer_list.html:
{% extends 'index.html' %}
{% load buttons %}
{% block content %}
<div class="pull-right">
{% if perms.App_CUS.customer_add %}
{% add_button 'App_CUS:customer_add' %}
{% delete_button 'App_CUS:customer_delete' %}
{% endif %}
</div>
<h1>{% block title %}Customers{% endblock %}</h1>
<div class="col-md-9">
<div class="table-responsive">
<table class="table table-hover table-headings table-bordered">
<thead>
<tr>
<th class="pk">
<input class="toggle" title="Toggle all" type="checkbox">
</th>
<th>ID</th>
<th>Customer Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
{% for customer in customers %}
<tr>
<th class="pk">
<input class="toggle" title="Toggle all" type="checkbox">
</th>
<td>{{ customer.pk }}</td>
<td>{{ customer.name }}</td>
<td>{{ customer.description }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
I would add to your existing
{% for customer in customers %}
a new td tag including something like:
<td>
<div class="checkbox">
<input type="checkbox" name="name_check_{{customer.name}}" id="id_check{{customer.name}}" value="1"
{%if customer.data == 0 %}unchecked {%else%} checked {%endif%}>
</div>
<td>
I've used customer.data to represent a value stored in your db.
You could then write some js to do something on click of each new checkbox.
<script>
$(document).ready(function() {
$("#id_check_{{customer.id}}").on("click", function(){
#do something / ajax call etc..
OR
pass these values back to the view on form post (we've named each checkbox unique to the customer), then process the deletions from there.

trying to get many-to-many related data in Django

I am building a website in Django where messages have tags. Below you can see my models.py
class Message(models.Model):
message_id = models.BigIntegerField(primary_key=True)
user = models.ForeignKey(User)
title = models.CharField(max_length=50)
tags = models.ManyToManyField(Tag, blank=True, null=True)
date_created = models.DateTimeField(auto_now_add=True)
def get_tags(self, tag_id):
return self.message.filter(tags__tag_id=tag_id)
class Tag(models.Model):
tag_id = models.BigIntegerField(primary_key=True)
tag_name = models.CharField(max_length=100)
date_created = models.DateTimeField(auto_now_add=True)
Here's my views.py as well.
popular_tags = Tag.objects.filter(messages__date_created__gt=now).annotate(num=Count('messages')).order_by('-num')[:25]
What I am trying to do here is that I want to show tags with the most number of messages. After I do that, I want the tags to show which messages have that tag. So I know I can't do query filtering in template, and that's why I added get_tags under the Message model. So with that I've tried writing the right template, but I am not sure what went wrong with it.
{% for q in popular_tags %}
<tr>
<td align="left"><h5>{{ q.tag_name }}</h5> </td>
{% for m in message.get_tags %}
<td align="left"><h5>{{ m.title }} </h5></td>
{% endfor %}
</tr>
{% endfor %}
I am not getting any errors, it's just that no messages are being shown while the tags are correctly displayed. Any ideas how and where I should fix?
You don't need anything special, Django's ORM takes care of it, cf https://docs.djangoproject.com/en/1.6/ref/models/relations/#related-objects-reference
The following should work:
{% for q in popular_tags %}
<tr>
<td align="left"><h5>{{ q.tag_name }}</h5> </td>
{% for m in q.message_set.all %}
<td align="left"><h5>{{ m.title }} </h5></td>
{% endfor %}
</tr>
{% endfor %}
You should add a function within Tag rather than Message:
class Tag(models.Model):
tag_id = models.BigIntegerField(primary_key=True)
tag_name = models.CharField(max_length=100)
date_created = models.DateTimeField(auto_now_add=True)
def get_msgs(self):
return Message.objects.filter(tags__tag_id=tag_id)
Hence, the template should be:
{% for q in popular_tags %}
<tr>
<td align="left"><h5>{{ q.tag_name }}</h5> </td>
{% for m in q.get_msgs %}
<td align="left"><h5>{{ m.title }} </h5></td>
{% endfor %}
</tr>
{% endfor %}

Categories