Access foreign key image in template - python

I have the following models:
class Car(models.Model):
# some fields
class CarPhotos(models.Model):
image = models.ImageField(upload_to='somewhere')
car = models.ForeignKey(Car)
in views.py:
def car_list(request):
cars = Car.objects.all()
return render(request, 'borsa/car_list.html', {'cars': cars})
in car_list.html:
{% for car in cars %}
<a href="car/{{ car.pk }}/view/">
<img class="media-object tmbpic" src="{{ car.carphotos_set.all.0.image.url }}" alt="kola">
</a>
The first method I've used was to use inline formsets but I had no clue how to access the images. Can you please point me in the right direction of how to access images according to Car objects ? I mean every Car must have a couple of images and I need to display only the first one in list view, but then I need to display all of them in Detail view.

To display all of them, you need to do something like:
{% for car in cars %}
{% for photo in car.carphotos_set.all %}
<img src="{{ photo.image.url }}">
{% endfor %}
{% endfor %}
So loop through the cars, then nest-loop through the images per car.

Related

displaying images using for loop in html

I am pretty new to django and now I'm currently learning how to access images in database and display it using html. I want to put the images as elements in a list for further styling and making the page responsive using css but I don't want to write each and every image as a list item as there are more than 100 images in database. I've tried the below code but its not displaying images as a list. Please do suggest if any better way of doing it. I have image as a model in my models.py.
<div class='gallery'>
{% for x in photo %}
<ul>
<li><img class="images" src="{{x.image.url}}"/></li>
</ul>
{% endfor %}
</div>
This is the model for reference:
from django.db import models
class Photo(models.Model):
photo_uploader = models.CharField(max_length=50)
desc = models.CharField(max_length=300)
image = models.ImageField(upload_to="home/images")
This is the view:
def profile(request):
username = None
if request.user.is_authenticated:
photos_to_show = []
username = request.user.username
photos = Photo.objects.filter(photo_uploader=username)
return render(request, 'profile.html', {'name': username, 'photo': photos})
The <ul> tags should be placed outside the loop, otherwise you each time start a new <ul> and end that </ul> per image:
<div class='gallery'>
<ul>
{% for x in photo %}
<li><img class="images" src="{{ x.image.url }}"/></li>
{% endfor %}
</ul>
</div>

How can I lists all the products according to their foreign key?

I am working on my first eshop website using django framework and I got stuck on a problem.
I have created a general model for different kinds of products (like laptops, books etc.). Each product that is added to the website can be found by on its foreign key that links that product to a specific category.
The question is how can I display on laptops.html only the products that have the foreign key which points to the right category? Like, to display only the products from laptops category.
Thank you very much for your time!
EDIT:
in urls:
urlpatterns=[
path('', views.HomePage.as_view(), name='home'),
path('ComputerScience/', views.ComputerScience.as_view(), name='computer_science'),
path('category/<int:category_pk>/list-products/', views.CompSProd.as_view(), name='category_products_list')]
In computerscience.html I render all the cateogries.
Here in views.py I have the two controllers, first for categories and second for laptops for instance.
views.py
class ComputerScience(ListView):
model = ComputerScienceCategory
template_name = "computer_science.html"
context_object_name = "category"
class CompSProd(ListView):
model = ComputerScienceProducts
template_name = "laptops.html"
context_object_name = "products"
def get_queryset(self):
queryset = super().get_queryset()
# If you wish to still keep the view only for specific category use below line
category = get_object_or_404(ComputerScienceCategory, pk=self.kwargs.get('category_pk'))
queryset = queryset.filter(category=category)
return queryset
Here I have the template where I want to display all categories.
computer_science.html
<div class="computerScienceContent" id="slide">
{% for cat in category %}
<a href="{% url 'category_products_list' category.pk %} " id="aBar">
<div>
<h4 class="cSh">{{ cat.name }}</h4>
<img src="{{ cat.img.url }}" alt="image" class="img">
</div>
</a>
{% endfor %}
Here is laptops html, where I'd like to have the whole products displayed.
laptops.html
{% extends 'index.html' %}
{% block title %}
<title>Laptops</title>
{% endblock %}
{% block cont2 %}
{% endblock %}
My main goal is that to have a page (computerscience.html) where I have displayed a list with all available categories and when you click on one category, to redirect you to another page where you have listed all the products that belongs to that category.
This is the error that has been thrown to me:
Reverse for 'category_products_list' with arguments '('',)' not found. 1 pattern(s) tried: ['category/(?P<category_pk>[0-9]+)/list\\-products/$']
You should override get_queryset to filter your objects. Also as you are writing a view for a specific instance of category you would end up writing a lot of views, also when a new category would be added this would be very tedious you should use one view for all categories instead. Try this:
from django.shortcuts import get_object_or_404
class CompSProd(ListView):
model = ComputerScienceProducts
template_name = "laptops.html"
context_object_name = "products"
def get_queryset(self):
queryset = super().get_queryset()
category = get_object_or_404(ComputerScienceCategory, pk=self.kwargs.get('category_pk')) # Assuming category_pk will be passed in url
# If you wish to still keep the view only for specific category use below line
# category = get_object_or_404(ComputerScienceCategory, pk=<pk-of-category-here>)
queryset = queryset.filter(category=category)
return queryset
To pass the categories primary key in the url you need to do something as follows:
In your urls.py:
urlpatterns = [
...
path('category/<int:category_pk>/list-products/', views.CompSProd.as_view(), name='category_products_list'),
...
]
Now in the page where you display all categories:
{% for cat in category %}
<a href="{% url 'category_products_list' cat.pk %}" id="aBar">
<div>
<h4 class="cSh">{{ cat.name }}</h4>
<img src="{{ cat.img.url }}" alt="image" class="img">
</div>
</a>
{% endfor %}
Also you write id="aBar" but this line is in a loop meaning you would end up with multiple same ids you should use a class instead.

Using related_name to call objects attributes in django templates

I have 3 models. User, Post and Proof. Posts are added by a User to the website. When other users do what the post says. They upload 2 images to say they did the task. The template will show the 2 images they uploaded. I know I am making some mistake in the template calling the images. Does anyone know the correct way to use related_name to call for the images. FYI I am new to python and Django I am sorry if this question is too trivial or has wrong logic
Proof/models.py
User = get_user_model()
class Proof(models.Model):
user = models.ForeignKey(User, related_name='proofmade')
post = models.ForeignKey(Post, related_name='postproofmade')
made_at = models.DateTimeField(auto_now=True)
image_of_task= models.ImageField()
proof_you_made_it = models.ImageField()
suggestions = models.TextField(max_length=1000)
def __str__(self):
return self.post.title
Templates
{% for user in post.made.all %}
<div class="container">
<img src="{{ user.proofmade.image_of_task.url }}" height="150px"/>
<img src="{{ user.proofmade.proof_you_made_it.url }}" height="150px"/>
</div>
{% endfor %}
Post/views.py
class PostDetail(SelectRelatedMixin, DetailView):
model = Post
select_related = ('user', 'group')
def get_queryset(self):
queryset = super().get_queryset()
return queryset.filter(user__username__iexact=self.kwargs.get('username'))
A ForeignKey is a one-to-many relationship; the related_name therefore gives access to a queryset corresponding to many items. You need to iterate over that queryset to get the individual items, in this case the Proof instances - just as you do with the users for each post. So, something like:
{% for user in post.made.all %}
{% for proof in user.proofmade.all %}
<div class="container">
<img src="{{ proof.image_of_task.url }}" height="150px"/>
<img src="{{ proof.proof_you_made_it.url }}" height="150px"/>
</div>
{% endfor %}
{% endfor %}

Django: best way to handle foreign key requests in template pages

Suppose you are making a site to simply list your products.
You want to upload an unspecified number of pictures for your each of your products. So you, following Django's many-to-one documentation, make two models:
# files stored under my_app/static/my_app/product_images/product_<id>/<img_name>
def product_img_dir_path(instance, filename):
return 'my_app/static/my_app/product_images/product_{0}/{1}'.format(instance.product.id, filename)
class Product(models.Model):
name = models.CharField ...
... # other attributes of the product, e.g. price, etc
class ProductImage(models.Model):
product = models.ForeignKey("Product", on_delete=models.CASCADE)
image = models.ImageField(upload_to=product_img_dir_path)
Now if I want all of the images for say product 1, I can retrieve them using:
ProductImages.objects.filter(product__pk=1)
My question starts here.
Suppose you want an index page which just shows the listings for all of your products and for simplicity, the first image associated with each product.
You make a template page with
{% for product in product list %}
<div class="product-listing" style="display:inline">
<!-- image for product goes here -->
<!-- brief description goes here -->
</div>
{% endfor %}
where product_list was passed in your context:
# inside /my_app/views.py
def index(request):
...
context = {"product_list": Product.objects.all()}
...
Question: what is the best way to also have access to the images for displaying the images in the template page?
Currently I thought constructing a parallel image list would suffice:
# inside /my_app/views.py
def index(request):
...
product_list = Product.objects.all()
image_list = [product.productimage_set.all()[0] for product in product_list]
context = {"product_list": product_list, "image_list": image_list}
...
and then somehow using the forloop counter to get the corresponding image for the product.
e.g.
{% for product in product list %}
<div class="product-listing" style="display:inline">
<img src="{{ image_list[<forloop counter>].image.url }}" />
<!-- brief description goes here -->
</div>
{% endfor %}
Is there a better way to do this?
As long as you can access product.productimage_set, you can try to iterate it in your template and do not pass it as a view context.
In your Django template:
{% for product in product_list %}
<div class="product-listing" style="display:inline">
{% for product_image in product.productimage_set.all %}
<img src="{{ product_image.image.url }}" />
<!-- brief description goes here -->
{% endfor %}
</div>
{% endfor %}
I think that it will be easier for you to solve this if you simplify your design by moving the images to your Product model.
If you want to save the path to an image it will be easier to use CharField, but if you want to save many paths why not using JSONField?
My suggestion look like this:
class Product(models.Model):
name = models.CharField(null=True, blank=True)
main_image = models.CharField(null=True, blank=True) # Optional
images = JSONField(null=True, blank=True)

How to display other entries of my filtered object in Django template

In my Django-Project I have a model, that looks like that:
class Tag_car(models.Model):
car = models.ForeignKey(Car)
tag = models.ForeignKey(Tag)
car is a foreign key of an ImageField and tag is a foreign key of a TextField.
Every car has more than only one tag.
Now users should be able to search for a specific car by a tag. I am doing it like that in my view:
…
search = request.POST.get('search')
cars = Tag_car.objects.filter(tag=search)
…
return render_to_response(page,context_instance=RequestContext(request, {'cars': cars}))
And in my Template I am displaying all cars then like that:
{% for car in cars %}
<img src="{{ MEDIA_URL }}{{ car.car }}">
{% endfor %}
It all works fine.
But now I also would like to display within the for-loop in the template all tags that are related to each car. When I do something like {{ car.tag }} I get obviously only the one tag for which the user was searching.
I am struggling how to pass all tags for each car to the view and then display them for each car.
Does anybody have an idea how to do that?
I appreciate your help.
So, the issue is that the object you're passing to the template as cars is actually a list of Tag_car objects. So, in order to get the list of other tags related to each car, you need to follow the relationship to the car, then query the other tags:
{% for car in cars %}
...
{% for tag in car.car.tag_set.all %}
...
{% endif %}
{% endif %}
Note though that you should probably query Car objects in the first place, rather than Tag_cars. Plus, your Tag_car model is really just the through table of a many-to-many relationship, so rather than creating it explicitly you can just use a M2M field on the Car model:
tags = models.ManyToManyField(Tag)
Iterate over car.tag.all in the template:
{% for car in cars %}
<img src="{{ MEDIA_URL }}{{ car.car }}">
<ul>
{% for tag in car.tag.all %}
<li>{{ tag }}</li>
{% endfor %}
</ul>
{% endfor %}
Also see: Traversing foreign key related tables in django templates

Categories

Resources