Pass multiple objects to templates with render - django

I'm beginner on Django.
I have a project with the following models:
My Articles models:
class Post(models.Model):
title = models.CharField(max_length=200)
slug = models.SlugField(max_length=160)
content = models.TextField()
image = models.ImageField(upload_to=upload_location)
timestamp = models.DateTimeField(auto_now=False, auto_now_add=True)
updated = models.DateTimeField(auto_now=True, auto_now_add=False)
categorie = models.CharField(max_length=200)
categorie = models.ForeignKey('categorie.Categorie')
publier = models.BooleanField()
My Portfolio categories models which is linked with my Article Model:
class Categorieport(models.Model):
title = models.CharField(max_length=200)
article = models.OneToOneField('posts.Post')
And finally, my portfolio models with all the photos:
class Portfolio(models.Model):
title = models.CharField(max_length=200)
image = models.ImageField(upload_to=upload_location)
timestamp = models.DateTimeField(auto_now=False, auto_now_add=True)
updated = models.DateTimeField(auto_now=True, auto_now_add=False)
categorieportfolio = models.ForeignKey('Categorieport')
In one view and one template, i'd like to display information concerning the article and the portfolio related to the article.
I wrote the following view:
def portfolio(request, article=None):
portfolio = get_object_or_404(Categorieport, article=article)
image_portfolio = portfolio.portfolio_set.all()
return render(request, 'portfolio1.html', {'portfolio': portfolio, 'image_portfolio': image_portfolio})
And the following templates:
<div class="titre-display">
<h2>{{ portfolio.article.timestamp|date:"d E Y" }} / {{ portfolio.article.categorie}} </h2>
<h1>{{ portfolio.article.title}}</h1>
</div>
<div class="content-display">
<div class="content-display-main">
<div class="content-display-main-portfolio">
<div class="image-portfolio">
<a class="example-image-link" href="{{ image_portfolio.image.url }}" data-lightbox="example-set" data-title="{{image_portfolio.title}}">
</a>
I can access to information from my article but i can't access information from my portfolio. I tried it with the shell, and it works. I can't figure out why it doesn't work in my view and template.
Do you have any idea?
Thank you in advance
Singertwist

Your image_portfolio is a querySet, that's means is some kind of list, you have to use a loop to access the items and them access the properties:
<div class="content-display">
<div class="content-display-main">
<div class="content-display-main-portfolio">
<div class="image-portfolio">
{% for item_img in image_portfolio %}
<a class="example-image-link" href="{{ item_img.image.url }}" data-lightbox="example-set" data-title="{{item_img.title}}"></a>
{% endfor %}

Try this:
# views.py
def portfolio(request, article=None):
# first get the Post instance with slug = article (I'm assuming article passed as url argument, is a slug)
post = get_object_or_404(Post, slug=article)
# get the Categoriepost object based on a specifi article
categorie_port = get_object_or_404(Categorieport, article=post)
# image_portfolio is a QuerySet (that is a list of Portfolio objects)
image_portfolio = categorie_port.portfolio_set.all()
return render(request, 'portfolio1.html', {'portfolio': categorie_port, 'image_portfolio': image_portfolio})
Leave your HTML as is.

Hi thank you all for your answer.
So, I used a for loop for solving my case as mentioned previously.
Below, my code:
<div class="titre-display">
<h2>{{ portfolio.article.timestamp|date:"d E Y" }} / {{ portfolio.article.categorie}} </h2>
<h1>{{ portfolio.article.title}}</h1>
</div>
<div class="content-display">
<div class="content-display-main">
<div class="content-display-main-portfolio">
{% for photo in image_portfolio %}
<div class="image-portfolio">
<a class="example-image-link" href="{{ photo.image.url }}" data-lightbox="example-set" data-title="{{photo.title}}">
{% thumbnail photo.image "300x300" crop="center" as im %}
<img class="example-image" src="{{ im.url }}" alt=""/>
{% endthumbnail %}
</a>
<p>{{photo.title}}</p>
</div>
{% empty %}
<p>Aucun portfolio.</p>
{% endfor %}
</div>
</div>
And my views:
def portfolio(request, slug=None, article=None):
slug = get_object_or_404(Post, slug=slug)
portfolio = get_object_or_404(Categorieport, article=article)
image_portfolio = portfolio.portfolio_set.all()
return render(request, 'portfolio.html', {'portfolio': portfolio, 'image_portfolio': image_portfolio})
Thanks again for your help
Singertwist

Related

Way to show latest 4 blog posts on my page

I want to be able to show the latest 4 blog posts only. I can't seem to get them to show. Any help would be greatly appreciated.
Here is my code:
Models.py
class BlogPost(models.Model):
blog_title = models.CharField(max_length=48)
blog_article = RichTextUploadingField(null=True, blank=True, default="ici")
blog_image = models.ImageField(null=True, blank=True, upload_to="images", default="default.png")
blog_date = models.DateField(auto_now_add=True)
blog_published = models.BooleanField(default=False)
blog_featured = models.BooleanField(default=False)
def __str__(self):
return self.blog_title
Views.py
def blogTest(request):
posts = BlogPost.objects.filter(blog_date__lte=timezone.now()).order_by('blog_date')
context_blog = {'posts': posts}
return render(request, 'blogtest.html', context_blog)
def latestPosts(request):
latest = BlogPost.objects.filter(blog_date__lte=timezone.now()).reverse()[:3]
return render(request, 'blogtest.html', {'latest': latest})
Template
<div class="blog-post-container">
<div class="row">
<h1 id="lastest-blogs-title" style="text-align: center;">Latest Blogs</h1>
{% for latestpost in latest %} {% if latestpost.blog_published is True %}
<div class="col-md-4" id="bloggrid1">
<hr>
<div class="blog-post">
<div class="blog-content">
<img class="blog-img"src="{{latestpost.blog_image.url}}"alt="My image"/>
<h2 class="blog-title">{{latestpost.blog_title}}</h2>
<hr id="blog-hr" style="width: 90%" />
<article class="blog-article">
<p>{{latestpost.blog_article|truncatechars_html:265|safe}}</p>
</article>
Read More...
<p class="blog-date">Posted on: {{latestpost.blog_date}}</p>
</div>
</div>
</div>
{% endif %} {% empty %}
<h3>No Blog Uploads</h3>
{% endfor %}
</div>
</div>
</div>
I have followed many other tutorials but I can't seem to see what I'm doing wrong here.
Try this if you want to get last 4 added entries based on primary key...
latest = BlogPost.objects.order_by('-pk')[:4]
Try this if you want to get last 4 added entries based on your date field
latest = BlogPost.objects.order_by('-blog_date')[:4]
Your template code is good to load entries passed through context
You need to sort queryset but not filter the queryset with blog_date
qs = BlogPost.objects.filter(blog_date__lte=timezone.now()).order_by('-blog_date')[:3]

Django Display count of database entries related via foreign key

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

How to display multiple images in a django template img element

I am having a challenge displaying multiple images users post to one img template element, for one reason if i try fetching images with the default related name it wouldn't show in the template and i wonder what i am doing wrong. Can anyone be of help!
Here is my model for post.
class Post(models.Model):
page = models.ForeignKey(Page, on_delete=models.CASCADE, related_name="page")
username = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE ,related_name="page_user")
description = models.TextField(max_length=500, blank=True)
video = models.FileField(upload_to="PageVideos", blank=True)
pic = models.ImageField(blank=True)
date_posted = models.DateTimeField(auto_now_add=True)
tags = models.CharField(max_length=100, blank=True)
class Mete:
ordering = ['-date_posted']
def __str__(self):
return self.description
class PostImage(models.Model):
#page = models.ForeignKey(Page, on_delete=models.CASCADE, related_name="pg")
post = models.ForeignKey(Post, default=None, on_delete=models.CASCADE)
images= models.ImageField(upload_to="postimages/")
Here is my Detail view
def page_detail(request,id):
post = get_object_or_404(Post, id=id)
photos = PostImage.objects.filter(post=post)
context = {
'post':post,
'photos':photos
}
return render(request, 'page/detail.html',context)
These my Template to display users images
<div class="p-3 border-b dark:border-gray-700">
{{ post.description }}
</div>
<div uk-lightbox>
<div class="grid grid-cols-2 gap-2 p-2">
{% for p in photos.images_set.all %}
<a id="images" href="{{ p.images.url }}" class="col-span-2" >
<img src="{{ p.images.url }}" alt="" class="rounded-md w-full lg:h-76 object-cover">
</a>
<a href="">
<img src="" alt="" class="rounded-md w-full h-full">
</a>
<a href="" class="relative">
<img src="" alt="" class="rounded-md w-full h-full">
<div class="absolute bg-gray-900 bg-opacity-30 flex justify-center items-center text-white rounded-md inset-0 text-2xl"> + see more </div>
</a>
{% endfor %}
</div>
</div>
your photos is a list you dont need reverse m2m (the "images_set") simply change this in html
....
<div class="grid grid-cols-2 gap-2 p-2">
{% for p in photos %}
....
for optimize you can do this
from django.http import Http404
...
def page_detail(request,id):
try:
# with prefetch you do only one sql request
post = Post.objects.select_related('images_set').get(id=id)
expect Post.DoesNotExist as err:
raise Http404(err)
context = {
'post': post,
'photos': post.images_set.all()
}
return render(request, 'page/detail.html',context)

Django template loop through items with parent ID or PK

I'm trying to set up magnific popup on django.
My goal is to have one main picture in the homepage overview gallery view, which when clicked, would open a popup with the related images from the same photoshoot i.e. images with the same ID or PK.
I tried to apply the following approach
but i just cannot get it to work, maybe someone could help me out in this
My models.py
class Item(models.Model):
name = models.CharField(blank=False, max_length=200)
category = models.ForeignKey(Category, blank=True, null=True, on_delete=models.SET_NULL)
order = models.IntegerField(blank=True, null=True)
active = models.BooleanField(blank=True, default=False)
objects = models.Manager()
class Meta:
verbose_name_plural = 'items'
def __str__(self):
return self.name
class ItemImage(models.Model):
image = ProcessedImageField(
blank=True,
null=True,
processors=[ResizeToFit(width=1680, upscale=False)],
format='JPEG',
options={'quality':90})
order = models.IntegerField(blank=True, null=True)
main = models.BooleanField(blank=True, default=False)
cover = models.BooleanField(blank=True, default=False)
item = models.ForeignKey(Item, related_name='items', blank=True, null=True, on_delete=models.SET_NULL)
objects = models.Manager()
class Meta:
verbose_name_plural = 'item images'
Views.py
def portraits(request):
port = ItemImage.objects.filter(item__category__slug='portraits', item__active=True, main=True,).order_by('item__order')
portall = ItemImage.objects.filter(item__category__slug='portraits', item__active=True).order_by('item__order')
context = {
'main_portraits': port,
'all_portraits': portall
}
return render(request, 'gallery/portraits.html', context)
and Template:
{% block content %}
<div class="grid">
{% for pic in main_portraits %}
<div class="item">
<div class="item">
<div class="outer-text">
<div class="text">
{{ pic.item.name }}
<p>Click to view gallery</p>
</div>
</div>
<a><img class="lazy" alt=""
sizes="(min-width:1400px) 1220px
(min-width:1000px) 1000px,
(min-width:500px) 700px,
(min-width:320px) 420px,
280px"
srcset="{{ pic.image_xs.url }} 280w,
{{ pic.image_s.url }} 420w,
{{ pic.image_m.url }} 700w,
{{ pic.image_l.url }} 1000w,
{{ pic.image_xl.url }} 1220w" />
</a> {{ pic.item.pk }}
</div>
<div class="lazy">
{% for p in all_portraits %}
{% endfor %}
</div>
</div>
{% endfor %}
</div>
{% endblock %}
I have set
z.item.pk
just as a test, to see if any of my manipulations result in the pk's to bunch up. For example the first for-loop returns a picture with PK "24", I need for the second for-lop to return only images with the same PK; and so for every image. I think the answer might be connected with _set.all function, just like in the related question above, but I cant seem to get it to work in my case. Feels like I'm missing something here.
current output:
<div class="grid">
<div class="item">
<div class="item">
<div class="outer-text">
<div class="text">
Palagā tītā
<p>Click to view gallery</p>
</div>
</div>
<a><img class="lazy" alt=""
sizes="(min-width:1400px) 1220px
(min-width:1000px) 1000px,
(min-width:500px) 700px,
(min-width:320px) 420px,
280px"
srcset="/media/CACHE/images/IMG_8329_3Vi8mYO_GD621ql/958ba5dbee5efe28fd2f5054b8f819e1.jpg 280w,
/media/CACHE/images/IMG_8329_3Vi8mYO_GD621ql/02d12ca7f0633fee2fc762cf96f7889e.jpg 420w,
/media/CACHE/images/IMG_8329_3Vi8mYO_GD621ql/ba5fa6633e92a288e3b2f47a713d64c2.jpg 700w,
/media/CACHE/images/IMG_8329_3Vi8mYO_GD621ql/fe0d559fef5b02434c43f841005d4961.jpg 1000w,
/media/CACHE/images/IMG_8329_3Vi8mYO_GD621ql/96d0e52dff14d1bc4b60bbec674565db.jpg 1220w" />
</a> 24
</div>
<div class="lazy">
</div>
</div>
You need prefiltered querysets containing the related images for every main image before handing over to the template.
def portraits(request):
ports = ItemImage.objects.filter(item__category__slug='portraits', item__active=True, main=True,).order_by('item__order')
for p in ports:
# You may not need the item__category__slug filter
# if there are only images of the same category
# associated with an item.
# Also, if you want to exclude the main image
# from the set of related images, you need to add the filter
# main=False
p.related_images = ItemImage.objects.filter(item__category__slug='portraits', item__id=p.item.id)
context = {
'main_portraits': ports,
}
return render(request, 'gallery/portraits.html', context)
Then you can loop over main_portraits in the template, and get the related images for each main image in a nested loop:
{% for mainp in main_portraits %}
{% for im in mainp.related_images %}
{# do something with the related images #}
{% endfor %}
{% endfor %}
You can break down the models like this it will make the querying easier.
# models.py
class Item(mdoels.Model):
name = models.CharField(blank=False, max_length=200)
category = models.ForeignKey(Category, blank=True, null=True, on_delete=models.SET_NULL)
...
display_image = models.ProcessedImageField(...)
class ItemImage(models.Model):
item = models.ForeignKey(Item, related_name='images', blank=True, null=True, on_delete=models.SET_NULL)
image = models.ProcessedImageField(...)
...
#views.py
def portraits(request):
items = Item.objects.filter(category__slug='portraits', active=True)
return render(request, 'gallery/portraits.html', context={items: items})
#template
{% for item in items %}
<h1> {{item.name}} </h1>
<img src={{item.display_image}} />
{% for item_image in item.images.all %}
<img src={{item_image.image}} />
{% endfor %}
{% endfor %}

How to implement the paginator in Django 2.1?

To product page of my project I need to add paginator. I did according to the Django Documentation but I have the following error:
object of type 'InsuranceProducts' has no len()
Here is the my views.py:
def farmer_types(request, type_id):
product_areas = InsuranceProducts.objects.filter(product_type="Фермерам")
product_types = get_object_or_404(InsuranceProducts, id=type_id)
paginator = Paginator(product_types, 6)
page = request.GET.get('page')
types = paginator.get_page(page)
context = {'product_types': product_types,
'product_areas': product_areas,
'types': types}
return render(request, 'insurance_products/farmer/farmer_types.html', context)
Here is the my models.py:
class InsuranceProducts(models.Model):
product_area = models.CharField(max_length=100)
product_description = models.TextField()
product_type = models.CharField(max_length=50)
def __str__(self):
return "{}-{}".format(self.product_area, self.product_type)
class ProductType(models.Model):
product_area = models.ForeignKey(InsuranceProducts, on_delete=models.CASCADE)
title = models.CharField(max_length=100)
description = models.TextField()
body = HTMLField('Content')
def __str__(self):
return "{} - {}".format(self.product_area, self.title)
Here is the code from the template:
{% for product in types.producttype_set.all %}
<div class="btmspace-80">
<h3>{{ product.title|upper }}</h3>
<img class="imgr borderedbox inspace-5" src="{% static 'img/imgr.gif' %}" alt="">
<p>
{{ product.description|upper }}
</p>
<p>
Подробно вы можете узнать о новости здесь</a>
</p>
</div>
{% endfor %}
<div class="pagination">
<span class="step-links">
{% if types.has_previous %}
« first
previous
{% endif %}
<span class="current">
Page {{ types.number }} of {{ types.paginator.num_pages }}.
</span>
{% if types.has_next %}
next
last »
{% endif %}
</span>
</div>
<!-- ################################################################################################ -->
</div>
I did the everything as it is given in the Docs.
Why is product_types plural if you are using get_object_or_404, which returns only one object?
You're doing the pagination right, but doing the query wrong. If you change paginator = Paginator(product_types, 6) to paginator = Paginator(product_areas, 6), you will see that it works perfectly fine.
You should read the documentation on how to do queries, and understand the relationships between models.