I am trying to display fields from child model 'usertraining' entry linked by foreign key to a 'training' entry. but second queryset usertraining_set does not seem to contain anything. What am I missing?
I have the following template loop:
{% for training in training_list %}
{% for elem in training.usertraining_set.all %}
<div class="training">
<div class="training-info">
<div class="training-main-title">
<div class="training-state">{{ elem.state }}</div>
{{ training.title }}
</div>
<div class="training-date">
<p>Last trained: {{ elem.last_training_date|date:"D, d M Y, H:i:s" }}</p>
</div>
<div class="training-score">
Score: <span class="badge btn-circle">{{elem.score}}</span>
</div>
</div>
<img src="{{ training.title_pic.url }}">
</div>
{% endfor %}
{% endfor %}
model
class Training(models.Model):
title = models.CharField(max_length = 2000, blank = False)
title_pic = models.ImageField(upload_to = 'training/title_pics', blank = False)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("training_detail",kwargs={'pk':self.pk})
#property
def title_pic_url(self):
if self.title_pic and hasattr(self.title_pic, 'url'):
return self.title_pic.url
class UserTraining(models.Model):
user = models.ForeignKey(User,related_name='usertraining',on_delete=models.CASCADE)
training = models.ForeignKey(Training,related_name='usedtraining',on_delete=models.CASCADE)
state = (
('train', 'train'),
('training', 'training...'),
('retrain', 'retrain'),
('trained','trained')
)
state = models.CharField(max_length = 200, choices = state, default = 'train')
last_training_date = models.DateTimeField(auto_now=True)
score = models.CharField(max_length = 4, default = '0%')
def __str__(self):
""" String representation of Training entry """
return "{}_{}".format(self.user,self.training)
You're using "related_name" in your UserTraining model fields:
user = models.ForeignKey(User,related_name='usertraining',on_delete=models.CASCADE)
training = models.ForeignKey(Training,related_name='usedtraining',on_delete=models.CASCADE)
_set postfix is used only when field has no related name, so in your templates it would be:
{% for elem in training.usertraining.all %}
Related
I have two models, ProjectNotes and ProjectNoteComments. ProjectNoteComments are related to ProjectNotes via a foreign key. I want to display the number of comments each note has on a listview. I am just learning Django and so far I have not been able to figure out how to retrieve and display the comment count.
My view:
(I do import count)
class ProjectNotesList(ListView):
model = ProjectNotes
template_name = 'company_accounts/project_notes.html'
comments = ProjectNotes.comments
def related_project(self, **kwargs):
project = get_object_or_404(Project, id=self.kwargs.get('pk'))
notes = ProjectNotes.objects.all
return notes
def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super().get_context_data(**kwargs)
context['project'] = get_object_or_404(Project, id=self.kwargs.get('pk'))
return context
commentscount = ProjectNotes.objects.annotate(num_comments=Count('comments'))
My template:
{% extends 'base.html' %}
{% block content %}
<div class="section-container container">
<h1>Notes for {{ project }}</h1>
{% if project.notes.all %}
{% for note in project.notes.all %}
<div class ="projectnotes-entry">
<div class="col-sm-8">
<div class="row-sm-6">
<div class="card mb-2">
<div class="card-body">
<div class="card-title">{{ note.title }}</div>
<div class="card-text">{{ note.body | safe | truncatewords:"20"|linebreaks }}
read more</div>
</div>
</div>
</div>
</div>
</div>
<h2>comments count</h2>
{{ commentscount }}
{% endfor %}
{% else %}
<p>No notes have been have been added yet.</p>
{% endif %}
</div>
{% endblock content %}
The models:
class ProjectNotes(models.Model):
title = models.CharField(max_length=200)
body = tinymce_models.HTMLField()
date = models.DateField(auto_now_add=True)
project = models.ForeignKey(Project, default=0, blank=True, on_delete=models.CASCADE, related_name='notes')
def __str__(self):
return self.title
class ProjectNoteComments(models.Model):
body = tinymce_models.HTMLField()
date = models.DateField(auto_now_add=True)
projectnote = models.ForeignKey(ProjectNotes, default=0, blank=True, on_delete=models.CASCADE, related_name='comments')
Short version:
{{ note.comments.all.count }} # possibly works also without 'all' but can't check right now
I've just answered similar problem with simple explanation of relationships.
https://stackoverflow.com/a/70955851/12775662
Read official docs, it's really rewarding. https://docs.djangoproject.com/en/4.0/topics/db/models/#relationships
template.html
{% for portfolioList in portfolio_list %}
<div class="jobster-timeline-item">
<div class="jobster-timeline-cricle">
<i class="far fa-circle"></i>
</div>
<div class="jobster-timeline-info">
<div class="dashboard-timeline-info">
<div class="dashboard-timeline-edit">
<ul class="list-unstyled d-flex">
<li><a class="text-right" href="{% url 'MyPortfolioUpdate' post_id=portfolioList.idx %}" role="button"> <i class="fas fa-pencil-alt text-info mr-2"></i> </a></li>
<li><i class="far fa-trash-alt text-danger"></i></li>
</ul>
</div>
<span class="jobster-timeline-time">{{portfolioList.start_date|date:"Y년 m월"}} ~ {{portfolioList.end_date|date:"Y년 m월"}}</span>
<h6 class="mb-2">{{portfolioList.subject}}</h6>
<span>-{{portfolioList.client_name}}</span>
<p class="mt-2">{{portfolioList.content|linebreaksbr}}</p>
<div class="row">
{% for portfolioImgList in portfolio_img_list %}
{% if portfolioImgList.portfolio_idx.idx == portfolioList.idx %}
<div class="col-md-6">
<img class="img-fluid" src="{{portfolioImgList.file.url}}" alt="" >
</div>
{% endif %}
{% endfor %}
</div>
</div>
</div>
</div>
{% endfor %}
view.py
q = Q()
q &= Q(user_idx = request.user.id)
portfolio_list = UserPortfolio.objects.filter(q).order_by('-idx')
q = Q()
q &= Q(portfolio_idx__user_idx = request.user.id)
portfolio_img_list = UserPortfolioFile.objects.filter(q).order_by('-idx')
return render(request, 'account/setting/portfolio_list.html', {"portfolio_list":portfolio_list, "portfolio_img_list":portfolio_img_list}
model.py
class UserPortfolio(models.Model):
idx = models.AutoField(primary_key=True)
user_idx = models.ForeignKey(
User,
db_column='user_idx',
on_delete=models.CASCADE
)
subject = models.CharField(max_length=255)
client_name = models.CharField(max_length=255)
client_service = models.CharField(max_length=255)
client_category = models.CharField(max_length=255)
start_date = models.DateTimeField()
end_date = models.DateTimeField()
content = models.TextField()
write_date = models.DateTimeField(auto_now = True)
update_date = models.DateTimeField(auto_now = True)
is_file = models.CharField(max_length=1)
class Meta:
managed = False
db_table = 'account_user_portfolio'
def portfolio_upload_to(instance, filename):
nowDate = datetime.now().strftime("%Y/%m/%d")
return '/'.join([str(instance.portfolio_idx.user_idx), instance.folder , nowDate, filename])
class UserPortfolioFile(models.Model):
idx = models.AutoField(primary_key=True)
portfolio_idx = models.ForeignKey(
UserPortfolio,
db_column='portfolio_idx',
on_delete=models.CASCADE
)
folder = 'portfolio'
file = models.ImageField(upload_to=portfolio_upload_to)
class Meta:
managed = False
db_table = 'account_user_portfolio_file'
This is result.
I want to use join orm in view.py. not like this. used 'if' in template.py
How can I do this? And I tried use join sql. but It was not worked.
I used prefetch_related this. but Its result was same as now.
And I think This is maybe good. doesn't?
Please answer something and thanks to every one
You can enumerate with .userportfoliofile_set.all:
{% for portfolioImgList in portfolioList.userportfoliofile_set.all %}
…
{% endfor %}
this will make a query to only retrieve the UserPortfolioFiles related to the portfolioList object.
In the view you can work with .prefetch_related(…) [Django-doc] to fetch all related items with one query, so:
def some_view(request):
portfolio_list = UserPortfolio.objects.filter(
user_idx=request.user.id
).prefetch_related('userportfoliofile_set').order_by('-idx')
return render(request, 'account/setting/portfolio_list.html', {'portfolio_list':portfolio_list})
I have a list of categories as well as a list of products my template is in such a manner that it has category sections each with a display of products that belong to said categories. I created a for loop for categories so as to easily display category sections for each category I create. I then went on to create a forloop for products within the category forloop with a condition so as to match products with their actual category before they are displayed under their category section. how can I slice the resulting products to limit the number of products shown
Models.py
class Category(models.Model):
name = models.CharField(max_length=120)
image_263x629 = models.ImageField(upload_to='cat_imgs')
image_263x629_2 = models.ImageField(upload_to='cat_imgs')
image_263x629_3 = models.ImageField(upload_to='cat_imgs')
img_array = [image_263x629, image_263x629_2, image_263x629_3]
description = models.CharField(max_length=250)
def __str__(self):
return self.name
class SubCategory(models.Model):
name = models.CharField(max_length=200)
description = models.CharField(max_length=300)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
def __str__(self):
return self.name
#def get_absolute_url(self):
# return reverse('subcat_detail', args=[str(self.id)])
class Product(models.Model):
name = models.CharField(max_length=120)
price = models.FloatField()
image_182x182 = models.ImageField(upload_to='pdt_imgs/')
image_1200x1200 = models.ImageField(upload_to='pdt_imgs/alt_imgs/')
image_600x600 = models.ImageField(upload_to='pdt_imgs/alt_imgs/')
image_600x600_2 = models.ImageField(upload_to='pdt_imgs/alt_imgs/')
image_300x300 = models.ImageField(upload_to='pdt_imgs/alt_imgs/')
img_array = [image_1200x1200, image_600x600, image_600x600_2]
sku = models.IntegerField()
available = models.BooleanField(default=True)
discount = models.IntegerField(default = 0)
description = models.CharField(max_length=120, blank=True, null=True)
brand = models.CharField(max_length=120, blank=True, null=True)
category = models.ForeignKey(SubCategory, on_delete=models.CASCADE)
seller = models.ForeignKey(Seller, on_delete=models.CASCADE)
Views
class HomePageView(ListView):
model = SubCategory
template_name = 'home.html'
queryset = SubCategory.objects.all()
def get_context_data(self, **kwargs):
context = super(HomePageView, self).get_context_data(**kwargs)
context['products'] = Product.objects.all()
context['pdts'] = Product.objects.order_by('?')[:12]
context['categories'] = Category.objects.all()
context['subcategories'] = SubCategory.objects.all()
return context
Template
{% for category in categories %}
<div class="ps-block--products-of-category">
<div class="ps-block__categories">
<h3>{{ category.name }}</h3>
<ul>
{% for subcategory in subcategories %}
{% if subcategory.category.name == category.name %}
<li>{{ subcategory.name }}</li>
{% endif %}
{% endfor %}
</ul><a class="ps-block__more-link" href="{% url 'cat_detail' category.id %}">View All</a>
</div>
<div class="ps-block__slider">
<div class="ps-carousel--product-box owl-slider" data-owl-auto="true" data-owl-loop="true"
data-owl-speed="7000" data-owl-gap="0" data-owl-nav="true" data-owl-dots="true" data-owl-item="1"
data-owl-item-xs="1" data-owl-item-sm="1" data-owl-item-md="1" data-owl-item-lg="1" data-owl-duration="500"
data-owl-mousedrag="off">
<img src="{{ category.image_263x629.url }}" alt="">
<img src="{{ category.image_263x629_2.url }}" alt="">
<img src="{{ category.image_263x629_3.url }}" alt="">
</div>
</div>
<div class="ps-block__product-box">
{% for product in products %}
{% if product.category.category.name == category.name %}
<div class="ps-product ps-product--simple">
<div class="ps-product__thumbnail"><a href="{% url 'pdt_detail' product.id %}"><img src="{{ product.image_300x300.url }}"
alt=""></a>
{% if product.discount > 0 %}
<div class="ps-product__badge">-{{ product.discount }}%</div>
{% endif %}
{% if product.available == False %}
<div class="ps-product__badge out-stock">Out Of Stock</div>
{% endif %}
</div>
<div class="ps-product__container">
<div class="ps-product__content" data-mh="clothing"><a class="ps-product__title"
href="{% url 'pdt_detail' product.id %}">{{ product.name }}</a>
<div class="ps-product__rating">
<select class="ps-rating" data-read-only="true">
<option value="1">1</option>
<option value="1">2</option>
<option value="1">3</option>
<option value="1">4</option>
<option value="2">5</option>
</select><span>01</span>
</div>
<p class="ps-product__price sale">UGX{{ product.price }}</p>
</div>
</div>
</div>
{% endif %}
{% endfor %}
</div>
</div>
{% endfor %}
Please do not filter in the template. You should filter in the view. A template implements rendering logic, not business logic*.
You can filter and slice in the view with:
def my_view(request):
# …
products = Product.objects.filter(category__name='specified category')[:10]
context = {
'products': products
}
return render(request, 'my_template.html', context)
This is not only the place where filtering belongs, it is also more efficient since we here will filter and slice on the database side. Typically a database can do this more efficient, and it furthermore limits the bandwidth from the database to the Django/Python layer.
Note (based on #SLDem's comment):
If you aim to filter children, you make use of a Prefetch object [Django-doc]. Indeed, imagine that we have a QuerySet of Categorys and we want to only retain Products that are available, we can use:
from django.db.models import Prefetch
categories = Category.objects.prefetch_related(
Prefetch(
'product_set',
Product.objects.filter(available=True),
to_attr='available_products'
)
)
then in the template we can render this with:
{% for category in categories %}
{% for product in category.available_products %}
…
{% endfor %}
{% endfor %}
I'like to represent the list of news_list, the result should be like following style using 2 loops:
category1
-- info_record 1
-- info_record 2
category2
-- info_record 3
The problem is, inside loop {% for m in p_list.p.name %} always nothing happen, meanwhile outside loop {% for p in p_category %} could be retrieved properly.
html template file is shown as below,
{% block content %}
<div class = "container">
{% for p in p_category %}
<div class = "row" >
......... {{p}}
</br>
</div>
{% for m in p_list.p.name %}
<div calss ="row">
.. <a href = "/pubinfo/{{m.slug}}" > {{m.title}} - [ {{m.created}}] </a>
</div>
{% endfor %}
{% endfor %}
</div>
{% endblock %}
the view file is shown as below,
from django.shortcuts import render
from datetime import datetime
from .models import Category
from .models import PostInfo
def list_all(request):
post_categories = Category.objects.all()
post_lists ={}
for cate in post_categories:
post_lists[cate.name] = PostInfo.objects.all().filter(category = cate)
import pdb; pdb.set_trace()
return render(request, 'pub_post.html', {'p_category': post_lists.keys(), "p_list": post_lists})
model file is shown as below,
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Category(models.Model):
name = models.CharField(max_length=200,
db_index=True)
slug = models.SlugField(max_length=200,
db_index=True,
unique=True)
class Meta:
ordering = ('name',)
verbose_name = 'category'
verbose_name_plural = 'categories'
def __str__(self):
return self.name
class PostInfo(models.Model):
title = models.CharField(max_length=200,
db_index=True)
slug = models.SlugField(max_length=200,
db_index=True,
unique=True)
content = models.TextField(blank=True,
null=True)
category = models.ForeignKey(Category,
related_name='post_category')
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
created_by = models.ForeignKey(User, related_name='created_by_user')
updated_by = models.ForeignKey(User, related_name='updated_by_user')
class Meta:
ordering = ('updated',)
# verbose_name = 'post'
# verbose_name_plural = 'posts'
def __str__(self):
return self.title
Appreciated if any one could give me your hand, thanks a lot again.
Thats because p_list is a dictionary.
Try this:
{% for key, value in p_list.items %}
{% if key == p %}
{% for m in value %}
<div calss ="row">
.. <a href = "/pubinfo/{{m.slug}}" > {{m.title}} - [ {{m.created}}] </a>
</div>
{% endfor %}
{% endif %}
{% endfor %}
.items convert the dictionary into a list of (key, value) pairs
Update, you can just replace the whole template with this and avoid the context variable p_category
{% block content %}
<div class = "container">
{% for p, values in p_list.items %}
<div class = "row" >
......... {{p}}
</br>
</div>
{% for m in values %}
<div calss ="row">
.. <a href = "/pubinfo/{{m.slug}}" > {{m.title}} - [ {{m.created}}] </a>
</div>
{% endfor %}
{% endfor %}
</div>
{% endblock %}
I want to show the calculated discount under every product. The code below has no errors, but it does not display the value.
models.py:
from django.db import models
# Create your models here.
CATEGORIES = (
('Electronics', 'Electronics'),
('Clothing', 'Clothing'),
)
class Products(models.Model):
Image = models.FileField()
ProductName = models.CharField(max_length = 250, default='')
Brand = models.CharField(max_length = 250, default='')
OriginalPrice = models.IntegerField(default = '')
Price = models.IntegerField(default = '')
Category = models.CharField(max_length = 250, choices = CATEGORIES)
class Meta:
verbose_name = 'Product'
verbose_name_plural = 'Products'
def DiscountCalc(self):
Discount = (Price/OriginalPrice) * 100
return self.Discount
def __str__ (self):
return self.ProductName
This is the template
index.html:
{% for product in AllProducts %}
<article class="product col-sm-3">
<a href="#" class="prodlink">
<img src="{{ product.Image.url }}" class="prodimg img-responsive">
<p class="prodname">{{ product.ProductName }}</p>
<span class="origprice">₹{{ product.OriginalPrice }}</span>
<span class="price">₹{{ product.Price }}</span>
<div class="discount">
<p>{{ product.Discount }}% off</p>
</div>
</a>
</article>
{% endfor %}
you need to make a property :
#property
def Discount(self):
return (self.Price/self.OriginalPrice) * 100
So now you can use product.Discount :)
Docs here Django model-methods
1)Defining a local variable and Returning a class variable will return null
2)You have to have the same name in models and template
models.py
def DiscountCalc(self):
Discount = (Price/OriginalPrice) * 100
return Discount
index.html
{% for product in AllProducts %}
<article class="product col-sm-3">
<a href="#" class="prodlink">
<img src="{{ product.Image.url }}" class="prodimg img-responsive">
<p class="prodname">{{ product.ProductName }}</p>
<span class="origprice">₹{{ product.OriginalPrice }}</span>
<span class="price">₹{{ product.Price }}</span>
<div class="discount">
<p>{{ product.DiscountCalc }}% off</p>
</div>
</a>
</article>
{% endfor %}