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
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]
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
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)
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 %}
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.