How to display multiple images for django model - html

Here is my image model, that I tied to the model Product
class Image(models.Model):
name = models.CharField(blank=True,max_length=20)
product = models.ForeignKey(Product)
image = models.ImageField(blank=True,null=True)
def __str__(self):
return self.name
Here is the view that I am using to try and display the images
def category(request, category_id):
categories = Category.objects.all()
images = Image.objects.all()
products = Product.objects.all()
try:
category = Category.objects.get(id=category_id)
except Category.DoesNotExist:
category = None;
template = loader.get_template('index.html')
context = {
'category': category,
'categories': categories,
'images': images,
'products': products
}
return HttpResponse(template.render(context,request))
and here is the html
{% for image in images %}
<img src="{{ image.url }}">
{% endfor %}
I know this definitely wouldn't work,but atleast this code displays the page instead of an error so i have been using it, can anyone please point me in the right direction to dipslay each image associated with each product.
Thank you!

You can try this:
{% for product in products%}
<p> {{product.name}} </p>
{% for simage in product.image_set.all %}
{% if simage.image%}
<img src="{{ simage.image.url }}">
{% endif %}
{% endfor %}
{% endfor %}

Related

Getting M2M field data in template Django

I want to get m2m data in my template through the views but failing to do so. The thing is that I'm able to show the data of m2m field looping it from template itself but it does slow down the website.
My Team apps Model looks like this:
class Team(models.Model):
title = models.CharField(max_length=255)
team_country = CountryField(max_length=200, blank=True, null=True)
members = models.ManyToManyField(User, related_name='teams')
created_by = models.ForeignKey(User, related_name='created_teams', on_delete=models.CASCADE)
Now in my tournament app I'm trying to get "members" of the team.
My Tournamet Views look like this:
def tournament_page(request, slug):
page = 'tournament_page'
user = request.user
tournament = Tournament.objects.get(slug=slug)
players = tournament.participants.select_related('user')
all_players = Profile.objects.select_related('user')
side_tourneys_ongoing = Tournament.objects.filter(state='Ongoing')[:10]
side_tourneys_upcoming = Tournament.objects.filter(state='Upcoming')[:10]
side_tourneys_completed = Tournament.objects.filter(state='Completed')[:10]
teams = Team.objects.select_related('created_by')
context = {
'page': page,
'tournament': tournament,
'side_tourneys_ongoing': side_tourneys_ongoing,
'side_tourneys_upcoming': side_tourneys_upcoming,
'side_tourneys_completed': side_tourneys_completed,
'teams': teams,
'players':players,
'all_players':all_players
}
Now I'm able to show the teams with their members in the template using for loop inside the template itself as:
Html template
<div class="grid-x">
{% for team in teams %}
{% for player in players %}
{% if team.id == player.active_team_id and team.game == tournament.game %}
<div class="wf-card event-team">
<div> {{team.title}} </div>
<div class="event-team-players">
{% for member in team.members.all %}
{{ member.username }}
{% endfor %}
</div>
</div>
{% endif %}
{% endfor %}
{% endfor %}
</div>
What I want is to use this piece of code
{% for member in team.members.all %}
{{ member.username }}
{% endfor %}
in my views since it causes the website to slow down and idk why.
What I tried in my views is:
all_teams = Team.objects.all()
members = all_teams.members.all()
and
members = Team.objects.all().prefetch_related('members')
First one throws an error:
'QuerySet' object has no attribute 'members'
Second one shows lots of blank records
Tried almost everything with search but none of them helped except using the code that I provided directly in the template itself.
Edited based on comments below. You should be able to do this more simply by prefetching team members.
views.py
def tournament_page(request, slug):
page = 'tournament_page'
user = request.user
tournament = Tournament.objects.get(slug=slug)
all_players = Profile.objects.select_related('user')
side_tourneys_ongoing = Tournament.objects.filter(state='Ongoing')[:10]
side_tourneys_upcoming = Tournament.objects.filter(state='Upcoming')[:10]
side_tourneys_completed = Tournament.objects.filter(state='Completed')[:10]
teams = Team.objects.select_related('created_by').prefetch_related('members')
template.html
<div class="grid-x">
{% for team in teams %}
{% if team.game == tournament.game %}
<div class="wf-card event-team">
<div> {{team.title}} </div>
<div class="event-team-players">
{% for member in team.members.all %}
{{ member.username }}
{% endfor %}
</div>
</div>
{% endif %}
{% endfor %}
</div>

Django/html issue with displaying/linking image

I'm making a site by using django. One of my models contains ImageField.
Files are saved in main_dir/media/images. I'd like to display specific images in templates but I can't achieve it. Instead of photo, I can see only default image icon which mean ( i guess ) that image is not found
settings.py
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
models
class Gallery(models.Model):
name = models.CharField(max_length=200)
author = models.ForeignKey(User, on_delete=models.CASCADE, default=None, null=True, blank=True)
date_posted = models.DateTimeField(auto_now_add = True)
def __str__(self):
return self.name
class Photo(models.Model):
gallery = models.ForeignKey(Gallery, on_delete=models.CASCADE, default=None, related_name='photos')
name = models.CharField(max_length=200)
description = models.TextField(blank=False)
image = models.ImageField(blank=True, upload_to='images')
views
def gallery(request, pk):
gallery_object = Gallery.objects.get(id=pk)
context = {'gallery':gallery_object}
return render(request, 'Gallery/gallery.html', context)
html
<!DOCTYPE html>
{% extends 'base.html' %}
{% block content %}
<h1>Gallery: {{ gallery.name }}</h1>
{% for photo in gallery.photos.all %}
<img src="{{photo.image.url}}">
<a>{{photo.image.url}}</a> #it's here only to check if path is correct
{% endfor %}
Go back to home page
{% endblock content %}
what should I change to display image correctly ?
you need to change the .get to .filter with the same condition to get multiple objects
because get will return 1 object only and you cant do the for loop in the template
There are a few things wrong. First of all, if you want to return multiple images then you have to use .filter() instead of .get() and if you are .get() instead of the filter then you don't have to loop over it as it is giving a single object. And the image is stored in Photos model and for that you will have to call that instead of gallery.
Here is how you can fix it:
For single object:
views function:
def gallery(request, pk):
gallery_object = Photos.objects.get(id=pk)
context = {'photo': photo_object}
return render(request, 'Gallery/gallery.html', context)
HTML template:
<!DOCTYPE html>
{% extends 'base.html' %}
{% block content %}
<h1>Gallery: {{ photo.name }}</h1>
<img src="{{photo.image.url}}">
<a>{{photo.image.url}}</a> #it's here only to check if path is correct
Go back to home page
{% endblock content %}
For returning multiple objects:
views function:
def gallery(request, pk):
gallery_object = Photos.objects.filter(#your query)
context = {'photos': photo_object}
return render(request, 'Gallery/gallery.html', context)
HTML:
<!DOCTYPE html>
{% extends 'base.html' %}
{% block content %}
{% for photo in photos %}
<h1>Gallery: {{ photo.name }}</h1>
<img src="{{photo.image.url}}">
<a>{{photo.image.url}}</a> #it's here only to check if path is correct
{% endfor %}
Go back to home page
{% endblock content %}
finally, i found an issue. I forgot about adding
urlpatterns+=static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)
to my urls.py file.
lmao

Trouble rendering results from searchbar in Django

I have been working on a search bar in django and I am close but having some issues rendering the results to the page.
Views.py
class SearchResultsView(ListView):
model = Project
template_name = 'search_results.html'
def get_queryset(self):
proj=self.request.GET.get('proj')
proj_list=Project.objects.filter(
Q(name__icontains=proj) | Q(projectTag__icontains=proj)
)
proj_list1=Project.objects.filter(
Q(department__icontains=proj)
)
proj_list2 = list(set(proj_list) & set(proj_list1))
return proj_list2
class SearchPageView(TemplateView):
template_name = 'searchbar.html'
search_results.html
{% extends 'main/base.html' %}
<html>
{%block content%}
<h1> Search Results </h1>
{% if proj %}
<ul>
{% for project in proj_list2%}
<li>
{{project.name}}, {{project.department}}, {{project.projectTag}}
</li>
{% endfor %}
</ul>
{% else %}
<h2>sorry, no results</h2>
{% endif %}
{%endblock%}
</html>
Whenever I search something that should definitely yield results, I get "sorry, no results."
Thank you. Please help me to understand my disconnect. The bigger aim for this is to then add different models to query from (i.e. not just search in projects, but also search by user).
You are checking the wrong variable. The collection of elements is object_list, not proj or proj_list2:
{% if object_list %}
<ul>
{% for project in object_list %}
<li>
{{project.name}}, {{project.department}}, {{project.projectTag}}
</li>
{% endfor %}
</ul>
{% else %}
<h2>sorry, no results</h2>
{% endif %}
The search is also quite odd, you only retrieve items if both the department and the name or the tag matches. We can simplify this to:
class SearchResultsView(ListView):
model = Project
template_name = 'search_results.html'
def get_queryset(self):
proj = self.request.GET.get('proj')
return =Project.objects.filter(
Q(name__icontains=proj) | Q(projectTag__icontains=proj),
department__icontains=proj
)
but it is odd that the department and the name for example should match. If you want to match any of the three, we can work with:
class SearchResultsView(ListView):
model = Project
template_name = 'search_results.html'
def get_queryset(self):
proj = self.request.GET.get('proj')
return =Project.objects.filter(
Q(name__icontains=proj) |
Q(projectTag__icontains=proj) |
Q(department__icontains=proj)
)

query prints objects instead of some names in django

Is there a simple way to remove query set objects in my template just to print product name without the objects
what it prints
class SellerAccountMixin(object):
products = []
def get_products(self):
account = self.get_account()
products = Product.objects.filter(seller=account)
self.products = products
return products
class SellerDashboard(SellerAccountMixin,FormMixin, View):
def get(self, request, *args, **kwargs):
context["products"] = self.get_products()
return render(request, "sellers/dashboard.html", context)
template
{% if products %}
<div class='pull-left col-sidebar '>
{{ products }}
</div>
You should iterate over your products, like:
{% if products %}
<div class='pull-left col-sidebar '>
{% for product in products %}{{ product.name }} {% endfor %}
</div>
{% endif %}
.name might be a different field. It should be the one you aim to render.

How to get image form another model in django

I want to get image form Image model for my Product model and show it cart template
This is my Code:
ecommerce/models.py
class Product(models.Model):
name = models.CharField(max_length=200)
content = models.TextField()
excerpt = models.TextField()
price = models.DecimalField(max_digits=6, decimal_places=2)
status = models.IntegerField(default=0)
date = models.DateTimeField(auto_now_add=True)
quantity = models.PositiveIntegerField()
author = models.PositiveIntegerField()
featured_image = models.CharField(max_length=300)
available = models.BooleanField(default=True)
def __str__(self):
return self.name
class Image(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
image = models.ImageField()
cart/views.py
#require_POST
def cart_add(request, product_id):
cart = Cart(request)
product = get_object_or_404(Product, pk=product_id)
form = CartAddProductForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
cart.add(product=product,
quantity=cd['quantity'],
update_quantity=cd['update'])
return redirect('cart:cart_detail')
def cart_detail(request):
cart = Cart(request)
for item in cart:
item['update_quantity_form'] = CartAddProductForm(initial={'quantity': item['quantity'],
'update': True})
return render(request, 'cart_detail.html', {'cart': cart})
cart/templates/cart.html
<tbody>
{% for item in cart %}
{% with product=item.product %}
<tr>
<td>
{% for product in products %}
<img src="{{ product.first_image.src }}" alt="" width="auto" height="340"/>
{% endfor %}
</td>
<td>{{ product.name }}</td>
.
.
.
</tr>
{% endwith %}
{% endfor %}
</tbody>
i have read this link
but it is no use to me, please help me, I am newby to this
Thank you
You should use reverse lookup image_set. To get first image do product.image_set.first.image.url:
<img src="{{ product.image_set.first.image.url }}" alt="" width="auto" height="340"/>
to get all images iterate over image_set:
{% for image in product.image_set.all %}
<img src="{{ image.src }}" alt="" width="auto" height="340"/>
{% endfor %}
Note you should remove this part:
{% for product in products %}
{% endfor %}
since you dont pass products variable into template context.