Adding multiple images on django admin site and showing on detail page - django

I'm working on a portfolio project and I want to add multiple images on the Django admin site then displaying one of the header_image and title of a project on the home/list page (like card class functionality in bootstrap) and other images on the detail page. Is it possible?
Models.py
class MultiImage(models.Model):
header_image = models.ImageField(upload_to='media/')
title = models.CharField(max_length=100)
other_images = models.ImageField(upload_to='media/') # want this to be multiple image field
description = models.TextField()
link = models.URLField()
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
publish = models.BooleanField(default=True)
class Meta:
ordering = ('created', 'updated')
def __str__(self):
return self.title
index.html
{% for project in projects %}
<div class="col-lg-4 col-md-6 portfolio-item filter-app">
<div class="portfolio-wrap">
<img src="{{ project.image.url }}" class="img-fluid" alt="">
<div class="portfolio-links">
<i class="bx bx-plus"></i>
<i class="bx bx-link"></i>
</div>
</div>
</div>
{% endfor %}
detail.html
<div class="container">
<div class="portfolio-details-container">
<div class="owl-carousel portfolio-details-carousel">
<img src="{% static 'img/portfolio-details-1.jpg' %}" class="img-fluid" alt="">
<!-- all the images goes here -->
</div>
<div class="portfolio-info">
<h3>Project Information</h3>
<ul>
<li><strong>Project </strong>: {{ project.title }}</li>
<li><strong>Project Link to GitHub:</strong>: <a href="{{ project.link }}">{{ project.title }}</a </li>
</ul>
</div>
</div>
</div>
list/index page img
detail page img1
detail page img2

If you want to have several images stored against a single MultiImage object, the best way to do this is to create a separate image model (where you will store all of the images) and then point them back to the MultiImage instance with a foreign key. It will look something like this:
class Image(models.Model):
# add in anything else you want here
image = models.ImageField((upload_to='media/')
multiImage = models.ForeignKey(Reporter, on_delete=models.CASCADE, related_name='other_images')
This will mean, each image you create 'points' to a MultiImage instance. The related_name property is how you get all of the images you need. For example:
multi_image_instance = MultiImage.objects.get(id=...)
images = multi_image_instance.other_images # this will return a QuerySet
In the detail view you can do something like:
{% for image in images %}
<img src={image.image.url} />
{% endfor %}

Related

How do I affect a single looped element in Django html?

I'm building an app in Django, using Bulma for styling. I have a Polishes model that has a favorites field, which references the User (users can save polishes to their list of favorites):
models.py:
class Polish(models.Model):
name = models.CharField(max_length=100)
image = models.CharField(max_length=400, default="https://www.dictionary.com/e/wp-content/uploads/2018/02/nail-polish-light-skin-tone.png")
brand = models.ForeignKey(Brand, on_delete=models.CASCADE, related_name='polishes')
favorites = models.ManyToManyField(User, related_name='favorite', default=None, blank=True)
def __str__(self):
return self.name
The add_favorites function checks to see if the polish has been added to the user's favorites already, and if it has, it removes the polish from the list. If it hasn't, it adds it:
views.py:
# login_required
def add_favorite(request, id):
polish = get_object_or_404(Polish, id=id)
if polish.favorites.filter(id=request.user.id).exists():
polish.favorites.remove(request.user.pk)
else:
polish.favorites.add(request.user.pk)
return redirect('favorites_list')
When I render the list of polishes, I'm using Bulma cards, displaying one polish per card. In the footer of the card, I want it to say 'Save to Favorites' if the polish is not in the user's list of favoties and 'Remove from Favorites' if it is. I'm struggling to get this piece to work. It will currently show either Save to Favorites or Remove from Favorites on all of the cards.
Does anyone have any insight on how to render a different message only on those that are already on the favorites list?
polish_list.html:
...
<div class="gallery">
{% for polish in polishes %}
<a href="{% url 'polish_reviews' polish.pk %}">
<div class="card">
<div class="card-header">
<p class="card-header-title">{{polish.name}} by {{polish.brand}}</p>
</div>
<div class="card-image">
<figure class="image is-square">
<img src="{{polish.image}}" alt="{{polish.name}}" />
</figure>
</div>
<footer class="card-footer">
{% if polish.favorites %}
Remove from Favorites
{% elif user.is_authenticated %}
Save to Favorites
{% else %}
Save to Favorites
{%endif%}
</footer>
</div>
</a>
{% empty %}
<article class="message">
<div class="message-header">
<p>No Polishes Available</p>
</div>
</article>
{% endfor %}
</div>
...
I have tried using a conditional in my polish_list.html - {% if polish.favorites %} - but this will make the change on all of the cards rather than just on those that are saved to favorites.

Have issues getting data to display on my web application

I am trying to get the "About us" information from my database to my web application but its not displaying, what could be wrong...
here is the code from the database
class About(models.Model):
about_us = models.TextField()
achieve = models.TextField(blank=True)
image_abt = models.ImageField(upload_to="admin_pics", null=True)
class Meta:
verbose_name_plural = "About Us"
def __str__(self):
return self.about_us
and here is the Html code `
{% extends 'jtalks/base.html' %}
{% load static %}
{%block content%}
<section id="about-home">
<h2>About Us</h2>
</section>
<section id="about-container">
{% for about in abouts %}
<div class="about-img">
<img src="{{ about.image_abt.url }}" alt="">
</div>
<div class="about-text">
<h2>Welcome to TechEduca, Enhance your skills with best Online Courses</h2>
<p>{ about.about_us}</p>
<div class="about-fe">
<img src="images/fe1.png" alt="">
<div class="fe-text">
<h5>400+ Courses</h5>
<p>You can start and finish one of these popular courses in under our site</p>
</div>
</div>
<div class="about-fe">
<img src="images/fe2.png" alt="">
<div class="fe-text">
<h5>Lifetime Access</h5>
<p>You can start and finish one of these popular courses in under our site</p>
</div>
</div>
</div>
{% endfor %}
</section>
{% endblock %}
Nothing is displaying in the frontend of the website.
Thanks for sharing the view. You forgot to pass data to your template. To do that you have to create the queryset and pass that into a dictionary like below. Add the context variable to your render method so you can access the data in the template.
def about(request):
about = About.objects.all()
context = {
'abouts': about,
}
return render(request, 'jtalks/about.html', context)
also, in your html code i see { about.about_us}, but you have to use double curly brackets: {{ about.about_us }}

Accessing a ManyToManyField in template

I am attempting to build a portfolio website and the idea was having a 'Project' model that contains multiple instances of an image. I think I was able to achieve this by using the 'ManyToManyField' relationship.
class Image(models.Model):
image = models.ImageField(upload_to='media/')
class Project(models.Model):
title = models.CharField(max_length=32)
description = models.TextField(default='', null=False)
stack = models.TextField(default='', null=False)
image = models.ManyToManyField(Image, related_name='images')
def __str__(self):
return self.title
From messing around a bit with the querying API, I've been able to retrieve the querysets for the images, but I am unsure how to keep those associated with their project and feed them into the context of my view. I already pass in an all() query for my Projects model (which is great), but I want to access the images as well.
Basically, I want my HTML template to end up looking like this:
{% for project in projects %}
<div class="card mx-auto" style="width: 50rem;">
<img class="card-img-top" src="{{ project.images }}" alt=""> // Issue here
<div class="card-body">
<p>{{ project }}</p>
<h5 class="card-title">{{project.title}}</h5>
<p class="card-text">{{project.description}}</p>
<p class="card-text">{{project.stack}}</p>
</div>
</div>
{% endfor %}
And here is the view:
def portfolio_view(request, *args, **kwargs):
p = Project.objects.all()
for project in p:
print('title: ', project.title)
print('description: ', project.description)
print('stack: ', project.stack)
print('images: ', project.image.all())
context = {
'projects': Project.objects.all(),
}
return render(request, 'main/portfolio.html', context)
Anything above the context object is just from testing.
Any help would be appreciated! Thanks a bunch!
Since you used a ManyToMany field, this means each project can have many images (and conversely each image can have many projects).
In this case you'll need to do something like this in your template:
{% for project in projects %}
...
{% for image in project.images.all %}
<img class="card-img-top" src="{{ image.image.url }}" alt="">
{% endfor %}
...
{% endfor %}
Let's assume we want only one image per project (and conversely only one project per image) i.e. a OneToOne field.
Your template would look like:
{% for project in projects %}
...
<img class="card-img-top" src="{{ project.image.image.url }}" alt="">
...
{% endfor %}

how can i use two types of queryset models override save method?

i want to ask you if i POST an article with featured=True then the old featured=true get transferred to featured=false queryset. i just want two [:2] values in featured=true queryset. here is the example of what i want
there are two article in featured=true queryset which i want the second article automatically get updated to featured=false when i create new article.
the output of my code when i applied is featuring only one article. were as i want two articles to be featured.
Here is the query of database with print(featured_articles.count()), photo of the list of articles in the admin, and the template.
models.py
class ArticleQuerySet(models.Manager):
def get_queryset(self):
return super(ArticleQuerySet,self).get_queryset().filter(status=True)
class Article(models.Model):
title = models.CharField(max_length=100)
author = models.ForeignKey(
User, on_delete=models.CASCADE, blank=True, null=True)
thumbnail = models.ImageField(default='def.jpg',
upload_to='article/thumbnails')
timestamp = models.DateTimeField(auto_now_add=True)
content = RichTextUploadingField(blank=True)
featured = models.BooleanField(default=False)
status = models.BooleanField(default=True)
tags = TaggableManager()
objects = models.Manager()
status_objects = ArticleQuerySet()
def __str__(self):
return self.title
class Meta:
ordering = ['-timestamp']
# i also try this method
def save(self, *args, **kwargs):
if self.featured == True:
Article.objects.filter(pk__in=(Article.objects.filter(featured=True,
).values_list('pk',flat=True)[:2])).update(featured=False)
self.featured = True
super(Article, self).save(*args, **kwargs)
views.py
from django.shortcuts import render
from .models import Article
def index(request):
featured_articles = Article.status_objects.filter(tags__exact='1', featured=True)[:2]
regular_articles = Article.status_objects.filter(tags__exact='1').exclude(pk__in=featured_articles)
context = {
'featured': featured_articles,
'regular': regular_articles,
}
return render(request, 'news/index.html', context)
index.html
<!--post header-->
<div class="post-head">
<h2 class="title"> Article </h2>
</div>
<!-- post body -->
<div class="post-body">
<div class="">
<!-- item one -->
<div class="item">
<div class="row">
<div class="col-sm-6 main-post-inner bord-right">
{% for nat in featured %}
<article>
<figure>
<a href="{% url 'news-detail' pk=nat.pk %}"><img src="{{ nat.thumbnail.url }}"
height="242" width="345" alt="" class="img-responsive"></a>
</figure>
<div class="post-info">
<h3>{{ nat.title }}
</h3>
<span>
<i class="ti-timer"></i>
{{ nat.timestamp | timesince }}
</span>
<p></p>
</div>
</article>
{% endfor %}
</div>
<div class="col-sm-6">
<div class="news-list">
{% for nat in regular %}
<div class="news-list-item">
<div class="img-wrapper">
<a href="{% url 'news-detail' pk=nat.pk %}" class="thumb">
<img src="{{ nat.thumbnail.url }}" alt="" class="img-responsive">
<div class="link-icon">
<i class="fa fa-camera"></i>
</div>
</a>
</div>
<div class="post-info-2">
<h5>{{ nat.title }}
</h5>
<i class="ti-timer"></i> {{ nat.timestamp | timesince }}
</div>
</div>
{% endfor %}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
Your code looks fine, but the standard way of doing this is keeping all marked as featured as is, without marking previous featured articles as featured=False:
views.py
def articles(self):
featured_articles = Article.status_objects.filter(tags__exact='1', featured=True)[:2]
regular_articles = Article.status_objects.filter(tags__exact='1').exclude(pk__in=featured_articles)
...
Note how .exclude(featured=True) is not in the regular_articles queryset. Old featured articles will automatically rollover into this queryset.
Some advantages of this approach are:
No need to maintain the list of featured articles
You get to keep a list of previously featured articles
You don't run into race conditions when multiple articles are being added/featured
You don't bother the database with updates
Your code is easier to maintain and read
Updating a single article doesn't have side effects (e.g. when you update an article, you know for sure you are only updating that article, nothing else)
That being said, there are times when you actually want to mark them as featured=false, but unless you have a compelling reason to, it's usually better to keep things simpler.
There is more better way for this. Create One new model like this.
remove featured field from your article model.
class featured (models.Model):
featured=models.OneToOneField(Article, related_name='featured', on_delete=models.CASCADE )
create as much featured article you want to featured.
suppose you want only two featured article, then create only two record.
whenever you want to change your featured article just update that record.
i hope this will be simple design and very flexible also you can increase featured article as much as you want by just adding new record and decrease as much as you want by just delete.
here you don't want to override your article save method.

Django: trying to link to one model inside of other models ListView

I would like to get the Restaurant Id from the Restaurant model and use it for the href in the Lunchmenu listview. DonĀ“t really know how to move forward from here. I have tried a for loop of the "restaurants_list" in the template but did not really understand how to get only one Id from the list.
Is there any way to do this in the template?
Should I change the View somehow?
Models:
class LunchMenu(models.Model):
restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE)
class Restaurant(models.Model):
manager = models.ForeignKey(User, on_delete=models.CASCADE)
restaurant_name = models.CharField(max_length=100)
Listview:
class LunchMenuListView(ListView):
template_name = "lunchmenus/lunchmenu_home.html"
model = LunchMenu
def get_context_data(self, **kwargs):
context = super(LunchMenuListView, self).get_context_data(**kwargs)
context["restaurants_list"] = Restaurant.objects.all()
return context
Template:
<div class="row">
{% for lunchmenu in lunchmenu_list %}
<div class="col-lg-4 col-sm-6 portfolio-item">
<div class="card h-100">
<img class="card-img-top" src="http://placehold.it/350x200" alt="">
<div class="card-body">
<h4 class="card-title">
{{lunchmenu.restaurant}}
</h4>
<p class="card-text">{{lunchmenu.description | safe}}</p>
</div>
</div>
</div>
{% endfor %}
</div>
{% endblock %}
Why not simply use restaurant field of the lunchmenu item like this:
<a href="/restaurants/{{ lunchmenu.restaurant.id }}">
Note that using hardcoded urls in this manner is not a best practice approach, you should use Django's built-in url template tag and use a named route which will give you a more robust solution with respect to the eventual changes in your urls scheme:
<a href="{% url 'restaurants:restaurant-detail' id=lunchmenu.restaurant.id %}">
(assuming that you have a restaurants:restaurant-detail route defined in your urls.py which takes restaurant.id as a parameter)