Displaying images "not featured" with featured images in Django template language - django

I am trying to display small thumbnail under featured images using django template language but for some reason main image displays fine but not small image. Idea is to display one featured image and rest as "not featured" images.
My single-page code to display "Featured Images" with "Not Featured" images is given below.
{% extends 'base.html' %}
{% block content %}
<h1>{{ product.title }}</h1>
{% for img in images %}
{% if img.featured %}
<h1>Featured</h1>
<img class='img-responsive' src="{{ MEDIA_URL }}{{ img.image }}"/>
{% else %}
<div class="col-xs-6 col-md-3">
<a href="#" class="thumbnail">
<img class='img-responsive' src="{{ MEDIA_URL }}{{ img.image }}"/>
</a>
</div>
{% endif %}
{% endfor %}
{% endblock %}
Please advise.
My models.py is....
from django.core.urlresolvers import reverse
from django.db import models
class Product(models.Model):
title = models.CharField(max_length=120)
description = models.TextField(null=True, blank=True)
price = models.DecimalField(decimal_places=2, max_digits=100, default=29.99)
sale_price = models.DecimalField(decimal_places=2, max_digits=100, null=True, blank=True)
slug = models.SlugField(unique=True)
timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
updated = models.DateTimeField(auto_now_add=False, auto_now=True)
active = models.BooleanField(default=True)
def __unicode__(self):
return str(self.title)
class Meta:
unique_together = ('title', 'slug')
def get_price(self):
return self.price
def get_absolute_url(self):
return reverse('single_product', kwargs={'slug': self.slug})
class ProductImage(models.Model):
product = models.ForeignKey(Product)
image = models.ImageField(upload_to='products/images/')
featured = models.BooleanField(default=False)
thumbnail = models.BooleanField(default=False)
active = models.BooleanField(default=True)
updated = models.DateTimeField(auto_now_add=False, auto_now=True)
def __unicode__(self):
return self.product.title

All the images were set as featured and that was causing issue. Thanks for help #f43d65. Also consulted project on Github at: https://github.com/codingforentrepreneurs/ecommerce/blob/master/ecommerce/templates/products/single.html.

Try to replace
{{ MEDIA_URL }}{{ img.image }}
to
{{ img.image.url }}

Related

Django imagefield don't shows on template

i've a model with an imageField and when i upload file works and in database adds file path to img field
but when i try call it in my template seem is always empity item.img instead other fields works well, to show it i use a listview model
def content_file_name(instance, filename):
ext = filename.split('.')[-1]
# filename = "%s_%s.%s" % (instance, instance.questid.id, ext)
return f"uploads/items/{instance.id}.{ext}"
class Item(models.Model):
type = models.IntegerField(choices=TYPE, blank=False, default=NO_CAT)
name = models.CharField(max_length=250 )
description = models.CharField(max_length=250, blank=True )
img = models.ImageField(upload_to=content_file_name, blank=True)
tags = models.ManyToManyField(Tag, through='Item_Tags')
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING)
active = models.BooleanField(default=False)
created = models.DateTimeField(default=timezone.now)
updated = models.DateTimeField(auto_now=True)
def __str__(self): #metodo righiesto
return self.name
my template
<div class="card-columns">
{% for item in page_obj %}
<div class="card">
{% if item.img %}
<img class="card-img-top" src="{{item.image.url}}" alt="Card image cap">
{% else %}
NO image
{% endif %}
<div class="card-body">
<h5 class="card-title">{{item.name}}</h5>
<p class="card-text">{{item.description}}</p>
<p class="card-text"><small class="text-muted"></small></p>
</div>
</div>
{% endfor %}
</div>

How to query from 2 Models in Class based views in django?

I have a model Log and another model Solutions and I am using DetailView to display details of each log
Each log can have many solutions.
There is a log field in the Solutions model that is Foreign Key to Log model..
Now how do I access both Log model and Solutions of that particular log in the same html template if I want to display all the solutions of that particular log below the details of the log
models.py:
class Log(models.Model):
title = models.CharField(blank=False, max_length=500)
content = models.TextField(blank=False)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
slug = models.SlugField(max_length=50, null=False, unique=True)
author = models.ForeignKey(User, on_delete=models.CASCADE,null=True, blank=True)
image = models.ImageField(
upload_to='images', blank=True)
def save(self, *args, **kwargs):
super().save()
self.slug = self.slug or slugify(self.title + '-' + str(self.id))
super().save(*args, **kwargs)
class Meta:
verbose_name = ("Log")
verbose_name_plural = ("Logs")
def __str__(self):
return f"{self.title}"
def get_absolute_url(self):
return reverse("log-detail", kwargs={"question": self.slug})
class Solutions(models.Model):
log = models.ForeignKey(
Log, on_delete=models.CASCADE, blank=True, null=True)
author = models.ForeignKey(User, on_delete=models.CASCADE,null=True, blank=True)
solution = models.TextField(null=True)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
slug = models.SlugField(max_length=50, null=False, blank=True)
image = models.ImageField(
upload_to='images', blank=True)
def save(self, *args, **kwargs):
self.slug = self.slug or slugify(self.solution)
super().save(*args, **kwargs)
class Meta:
verbose_name = ("Solution")
verbose_name_plural = ("Solutions")
def __str__(self):
return f" {self.solution} "
views.py:
class LogDetailView(DetailView):
model = Log
slug_url_kwarg = 'question'
slug_field = 'slug'
log_detail.html:
{% extends 'log/base.html' %}
{%load crispy_forms_tags %}
{% block content %}
<title>Error Logger - {{object.title}}</title>
<div class="main container mt-4 p-3 mb-4">
<img style='display:inline;' class='rounded-circle account-img' src="{{ object.author.profile.avatar.url }}" alt="">
<h1 style='display:inline;'>
{{ object.title }}
</h1>
<p>Author: {{ object.author }}</p>
<p>Date and time of creation: {{ object.created }}</p>
<span> Details </span>:
<p class="big ml-4">{{ object.content }} <br />
{% if object.image %}
<img style="width: 20vw" class="mt-4" src="{{ object.image.url }}" alt="image" />
{% else %}
{% endif %}
</p>
</div>
<br />
<a
class="btn btn-outline btn-info button-solution"
href="#"
>Add solution</a
>
You can enumerate over these in the template by accessing the relation in reverse, this is normally modelname_set, unless you set a related_name=…. So in this case it is solutions_set:
{% for solution in object.solutions_set.all %}
{{ solution }}
{% endfor %}
If the ForeignKey has a related_name=… [Django-doc], for example with:
class Solutions(models.Model):
log = models.ForeignKey(
Log,
on_delete=models.CASCADE,
blank=True,
null=True,
related_name='solutions'
)
# …
Then we access this with:
{% for solution in object.solutions.all %}
{{ solution }}
{% endfor %}
Note: normally a Django model is given a singular name, so Solution instead of Solutions.

Django queryset Product model and Product_images model, TemplateSyntaxError

I am developing an ecommerce website with Django. I had Product and Product_images models as below:
class Product(models.Model):
tags = models.ManyToManyField(Tag, related_name='products')
same_product = models.ManyToManyField('self', related_name='same_products', blank=True)
category = models.ForeignKey('Category', on_delete=models.CASCADE, related_name='product_categories')
who_like = models.ManyToManyField(User, related_name='liked_products', blank=True)
title = models.CharField('Title', max_length=100, db_index=True)
slug = models.SlugField('Slug', max_length=110, unique = True)
sku = models.CharField('SKU', max_length=50, db_index=True)
description = models.TextField('Description', null=True, blank=True)
sale_count = models.IntegerField('Sale Count', default=0)
is_new = models.BooleanField('is_new', default=True)
is_featured = models.BooleanField('is_featured', default=False)
is_discount = models.BooleanField('is_discount', default=False)
price = models.DecimalField('Price', max_digits=7, decimal_places=2)
discount_value = models.IntegerField('Discount Value', null=True, blank=True)
def __str__(self):
return self.title
class Product_images(models.Model):
# relations
product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='images')
# informations
image = models.ImageField('Image', upload_to='media/product_images')
is_main = models.BooleanField('Main Image', default=False)
is_second_main = models.BooleanField('Second Main Image', default=False)
# moderations
status = models.BooleanField('Status', default=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
db_table = 'image'
verbose_name = 'Image'
verbose_name_plural = 'Images'
ordering = ('created_at',)
def __str__(self):
return f'{self.image}'
In my Product_images model I store several images for one Product, in Product_images model I wrote
boolean fields with names is_main and is_second_main. In my template I want to get these images, in my terminal (interactive shell) when I write single_product.images.get(is_main=True).image.url can get image url, but in template I can't get image, but get an error as below:
TemplateSyntaxError at /
Could not parse the remainder: '(is_main=True).image.url' from 'product.images.get(is_main=True).image.url'
Below is my view and template:
def index(request):
products = Product.objects.all()
context = {
'products': products
}
return render(request, 'index/index.html', context)
{% for product in products %}
<div class="front">
<a href="product-page(no-sidebar).html">
<img src="{{ product.images.get(is_main=True).image.url }}" class="img-fluid blur-up lazyload bg-img" alt="">
</a>
</div>
<div class="back">
<a href="product-page(no-sidebar).html">
<img src="{{ product.images.get(is_main=True).image.url }}" class="img-fluid blur-up lazyload bg-img" alt="">
</a>
</div>
{% endfor %}
Please, help me with this problem and properly display these images, thanks in advance.
I already solve this problem, maybe it is not the best way, but work.
{% for product in products %}
<div class="product-box">
<div class="img-wrapper">
<div class="front">
<a href="{% url 'product-detail' product.slug %}">
{% for image in product.images.all %}
{% if image.is_main %}
<img src="{{ image.image.url }}" class="img-fluid blur-up lazyload bg-img" alt="">
{% endif %}
{% endfor %}
</a>
</div>
<div class="back">
<a href="{% url 'product-detail' product.slug %}">
{% for image in product.images.all %}
{% if image.is_second_main %}
<img src="{{ image.image.url }}" class="img-fluid blur-up lazyload bg-img" alt="">
{% endif %}
{% endfor %}
</a>
</div>
{% endfor %}

After using prefetch_related still facing n+1

I am facing multiple duplicate db call even after I am using prefetch_related.
Here is my views:
def index(request):
product_qs = Product.objects.filter(shop_type='Grocery', featured=True, hide=False)
product_list = product_qs.prefetch_related('image', 'size_list').order_by('ranking')
products = terminator(request, product_list, 25) // reusable paginator!
context = {'categories': categories, 'products': products}
return render(request, 'grocery/index.html', context)
Here is my models:
class ProductImage(models.Model):
image = models.ImageField(upload_to='shop/product')
color = models.BooleanField(default=False)
image_thumbnail_index = ImageSpecField(source='image',
processors=[ResizeToFill(308, 412)],
format='JPEG',
options={'quality': 100})
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Product(models.Model):
shop_type = models.CharField(choices=shop_options, max_length=40)
name = models.CharField(max_length=200, unique=True)
image = models.ManyToManyField(ProductImage)
category = TreeForeignKey('Category', null=True, blank=True, on_delete=models.PROTECT)
slug = models.SlugField(max_length=200, db_index=True)
featured = models.BooleanField(default=False)
size = models.BooleanField(default=False)
size_list = models.ManyToManyField(SizeList)
available = models.BooleanField(default=True) # out of stock ?
hide = models.BooleanField(default=False) # archive a product
ranking = models.PositiveIntegerField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
and the template:
<figure class="product-image-container">
<a href="#" class="product-image">
<img src="{{ product.image.first.image_thumbnail_index.url }}" alt="{{ products.name }}">
</a>
{% trans 'Quickview' %}
</figure>
<div class="product-details">
<h2 class="product-title">
<a href="/grocery/product/{{ product.slug }}">
{% if LANGUAGE_CODE == 'en' %}
{{ product.name }}
{% else %}
{{ product.name_bn }}
{% endif %}
</a>
</h2>
<div class="price-box">
<span class="product-price">
{% if LANGUAGE_CODE == 'en' %}
৳ {{ product.price }}
{% else %}
৳ {{ product.price_bn }}
{% endif %}
</span>
</div><!-- End .price-box -->
Screenshot of sql calls:
Since you are already prefetching the ProductImage objects you may use the of the prefetched objects: {% with product.image.all|first as image %}{{ image.image_thumbnail_index.url }}(% endwith %}. (While calling first() does an extra query using LIMIT 1 at the end.)

Get Featured Image from different Model

I have 2 model objects, Business & BusinessImage as so, listed with views and index.html. I am trying to list the business's featured image, but it's not happening. I am getting the following error:
'QuerySet' object has no attribute 'businessimage_set'
How can I get the business featured image for a list?
Business
class Business(models.Model):
name = models.CharField("Name", max_length=70, default="Business Name")
slug = models.SlugField()
description = models.TextField("About", max_length=400)
category = models.ManyToManyField(Category, verbose_name="Categories", blank=True)
order = models.IntegerField("Order", default=0)
claimed = models.BooleanField("Claimed", default=False)
featured = models.BooleanField("Featured", default=False)
class Meta:
ordering = ['order']
verbose_name = "Business"
verbose_name_plural = "Businesses"
def __str__(self):
return self.name
BusinessImage
class BusinessImage(models.Model):
business = models.ForeignKey(Business)
image = models.ImageField(upload_to="images/business")
title = models.CharField(max_length=120)
featured = models.BooleanField(default=False)
timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
updated = models.DateTimeField(auto_now_add=False, auto_now=True)
def __str__(self):
return self.title
view.py
from .models import Business, BusinessImage
def index_view(request):
latest_business_list = Business.objects.all()
images = latest_business_list.businessimage_set.all()
template = loader.get_template('index.html')
context = RequestContext(request, {
'latest_business_list': latest_business_list,
'images': images,
})
return HttpResponse(template.render(context))
index.html
{% block content %}
<div class="text-center business_title">
<h2>Featured</h2>
</div>
{% if latest_business_list %}
{% for business in latest_business_list|slice:":4" %}
{% if business.active %}
<div class="col-sm-6 col-md-3">
<li>{{ business.name }}</li>
{% for image in latest_business_list.businessimage_set.all %}
{% if image.featured %}
<a href="{% url 'single_product' product.slug %}">
<img src="{{MEDIA_URL}}{{image.image}}" alt="{{image}}">
</a>
{% endif %}
{% endfor %}
</div>
{% endif %}
{% endfor %}
{% endif %}
{% endblock %}
businessimage_set is an attribute of a Business instance, but you're trying to access it as an attribute of a queryset (i.e. list of businesses). If your goal is just to be able to access the images for each business in a template, you can leave out images entirely. Instead your template would have:
{% for image in business.businessimage_set.all %}
(Though look into prefetch_related for efficiency.)