Bulk download of images rendered under mulitple categories in a single html page - django

I have lot of images stored in a single folder in a S3 bucket. There are three categories(let's say A, B and C) and an image would fall into only one of the three categories. I am rendering all the images category wise on view-all.html page. What I am trying to do is add a separate download button beside the name of each category in the view-all.html. Upon clicking on a particular download button, the images present only under that category should be downloaded as a zip-file. Currently the download buttons are not working for any of the categories.
I have edited only the view-all.html and the views.py files. I searched a lot about this but didn't find any exact solution. I am not sure whether I have to add anything else in any other file. Please help me out. Thanks in advance.
view-all.html
{% extends "cms/base.html" %}
{% block title %}
View-all
{% endblock %}
{% block main %}
<style>
*{box-sizing: border-box;}
.wrapper{
overflow-x:scroll;
white-space: nowrap;
}
.container {
background: #ccc;
position: relative;
height: 50%;
display: inline-block;
}
img {
padding: 0;
display: block;
margin: 0 auto auto 0;
margin-left: auto;
margin-right: auto;
max-width: 100%;
}
.overlay {
position: absolute;
bottom: 0;
background: rgb(0, 0, 0);
background: rgba(0, 0, 0, 0.5);
color: #f1f1f1;
width: 93%;
transition: .5s ease;
opacity:0;
color: white;
font-size: 20px;
padding: 20px;
text-align: center;
}
.container:hover > .overlay {
opacity: 1;
}
#media only screen and (max-width : 767px)
{
height: auto;
max-height: none;
}
</style>
{% for category in categories %}
<br /><h3>{{ category.name }}  <button name='downloadbtn' class="btn btn-primary" onclick='bulkdownload()'><i class="fa fa-download"></i> Download</button> </h3>
<div class="wrapper">
<div id="slider4" class="text-center">
{% for image in images %}
{% ifequal image.category category %}
<div class="container">
<img src="S3-url">
<br />
</div>
{% endifequal %}
{% endfor %}
</div>
</div>
{% endfor %}
{% endblock %}
views.py
#login_required
def bulkdownload(request):
if(request.GET.get('downloadbtn')):
images = Images.objects.all().filter(category = request.category.name)
if images:
categories = request.category.name
zip_subdir = '{:%B %d, %Y}'.format(datetime.now()) # name of the zip file to be downlaoded
zip_filename = '%s.zip' % zip_subdir
# Open StringIO to grab in-memory ZIP contents
s = io.StringIO.StringIO()
# The zip compressor
zf = zipfile.ZipFile(s, 'w')
for fpath in images:
# Calculate path for file in zip
fdir, fname = os.path.split(fpath)
zip_path = os.path.join(zip_subdir, fname)
# Add file, at correct path
zf.write(fpath, zip_path)
# Must close zip for all contents to be written
zf.close()
# Grab ZIP file from in-memory, make response with correct MIME-type
resp = HttpResponse(s.getvalue(), content_type = 'application/x-zip-compressed')
# ..and correct content-disposition
resp['Content-Disposition'] = 'attachment; filename=%s' % zip_filename
return resp

You can create forms and POST the data to download the images as:
{% for category in categories %}
<form method='POST' action="{% url 'your_url_name_for_view' %}">
<br /><h3>{{ category.name }}  
<input type="hidden" value="{{ category.id }}" name="category_id">
<input name='downloadbtn' class="btn btn-primary" type="submit"><i class="fa fa-download"></i> Download</h3>
</form>
<div class="wrapper">
<div id="slider4" class="text-center">
{% for image in images %}
{% ifequal image.category category %}
<div class="container">
<img src="S3-url">
<br />
</div>
{% endifequal %}
{% endfor %}
</div>
</div>
{% endfor %}
Now in your view you can check for the category as:
if request.method == 'POST':
category_id = request.POST.get('category_id')
images = Images.objects.all().filter(category_id = category_id)
Hope it helps.

Related

How to display a specific color depending on the values of a variable in Django?

For example, if the application.status is "rejected", then background: gray; color: lightgrey. If "accepted" - green and lightgreen. If "in progress", then blue and light blue.
<div>
{% for application in object_list %}
<div style="background: ???; color: ???;">
<span>{{ application.status }}</span>
</div>
</div>
{% endfor %}
</div>
Firstly, be careful about your for loop, which currently produces invalid HTML (Currently each iteration opens 1 div but closes 2 divs). I've made the appropriate correction in my answer below.
Secondly, it is perfectly valid DTL (Django Template Language) to put {% if %}, {% elif %} and {% else %} blocks inside HTML tags, so that you can generate dynamic attributes.
In your case for styling the color by status, it would look something like this:
<div>
{% for application in object_list %}
<div
{% if application.status == "rejected" %}
style="background: gray; color: lightgrey"
{% elif application.status == "accepted" %}
style="background: green; color: lightgreen"
{% endif %}
>
<span>{{ application.status }}</span>
</div>
{% endfor %}
</div>
Depending on your IDE/Text-Editor settings, you may get some weird syntax highlighting when you do this, but it should produce great output. I use this trick all the time myself.
To set the background and text color of a div element based on the value of the application.status variable in Django templates, you can use conditional statements and CSS classes. Here's an example:
Define CSS classes for each status:
CSS
.rejected {
background-color: gray;
color: lightgrey;
}
.accepted {
background-color: green;
color: lightgreen;
}
.in-progress {
background-color: blue;
color: lightblue;
}
In your Django template, use conditional statements to add the appropriate CSS class to the div element based on the application.status value:
HTML
<div>
{% for application in object_list %}
<div class="{% if application.status == 'rejected' %}rejected{% elif application.status == 'accepted' %}accepted{% elif application.status == 'in progress' %}in-progress{% endif %}">
<span>{{ application.status }}</span>
</div>
{% endfor %}
</div>
This will add the appropriate CSS class to each div element based on the value of application.status, which will set the background and text color of the element as defined in the CSS class.

Embed PDF in Django template

I am trying to embed a pdf in a Django template. I am using the same way we are embedding an image in django. It`s seems that the file cannot be found. Is there a different way to display it?
Many Thanks
views.py
class BillDetailView(generic.DetailView):
model = Bill
template_name = 'accounting/bills/bill_detail.html'
models.py
class BillFile(models.Model):
bill = models.ForeignKey(Bill,on_delete=models.CASCADE, blank=True, null=True, unique=False)
bill_file = models.FileField(upload_to='media/bill_files/', default='bill_files/default_id.jpg', blank =True)
bill_detail.html
<div class="card-block">
{% if billfile.bill_file %}
<div class="top-right"></div>
<!-- Option 1 -->
<embed src="{{ billfile.bill_file.url }}" width = "200" height = "240" style =" margin-left: auto; margin-right: auto; display: block;">Click me</a>
<!-- Option 2 -->
<iframe src="{{ billfile.bill_file.url }}" style="width: 100%;height: 100%;border: none;"></iframe>
<!-- Option 3 -->
Click me
{% else %}
<h3>There is no file to display</h3>
{% endif %}
</div>

django templates with-tag custom filter

I have a dict of lists containing images. The key is the id of a journey. Now I want to get an image list based on the id so I wrote a filter:
#register.filter
def dict_value(dict, key):
return dict.get(key)
Now I want to use this filter but how? This is what I did:
{% for journey in journeys %}
...
{% with imagelist={{ images|dictvalue:{{journey.id}} }} %}
{% if imagelist %}
<img class="card-img-top" data-src="" style="height: 225px; width: 100%; display: block;" src="{{imagelist.0.url}}" data-holder-rendered="true">
{% else %}
<img class="card-img-top" data-src="" style="height: 225px; width: 100%; display: block;" src="https://via.placeholder.com/348x225.png" data-holder-rendered="true">
{% endif %}
{% endwith %}
...
{% endfor %}
For testing, I want to display the first image if the list is not empty.
But I have a problem with the with-tag. How do I do it correctly?
In a template filter, you do not need to use extra double curly brackets, you can write this as:
{% with imagelist=images|dictvalue:journey.id %}
That being said, it is normally not a good idea to implement business logic in the template. Normally one does this in the view.

Can Django admin user edit the base.html page from backend?

I'd like to edit the background image of in the base.html template. I was thinking of having a model and form, that way the user/admin can just upload new images to the background. The issue I think I'm having is referencing the base.html template directly since it's never called directly.
I was thinking of just pushing the style in line, or editing the CSS directly would be cool too. I just have only been able to toggle different CSS prewritten codes
I've tried having a base_view(request) but doesn't work
(base.html is never called, so I assume that's why and obviously the extended pages don't modify the base.html)
def base_view(request):
context = {
'post': BackgroundImage.objects.last()
}
return render(request, 'base.html', context)
So this is what I have:
models.py:
class BackgroundImageModel(models.Model):
image = models.ImageField(default="default.jpg", upload_to='background_pics')
author = models.ForeignKey(User, on_delete=models.CASCADE)
def save(self):
super().save()
img = Image.open(self.image.path)
if img.height > 2000 or img.width > 2000:
output_size = (2000, 2000)
img.thumbnail(output_size)
img.save(self.image.path)
views.py:
class BackgroundImage(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = BackgroundImageModel
fields = ['image']
base.html:
{% if background %}
<body style="background:
url({{ background.image.url }})
repeat fixed center;
margin: 5rem 0 2rem 0;">
{% else %}
<body style=" margin: 5rem 0 2rem 0;">
{% endif %}
You're passing the image as post in your context but you're using background in the html.
Try:
{% if background %}
<body style="background:
url({{ post.image.url }})
repeat fixed center;
margin: 5rem 0 2rem 0;">
{% else %}
<body style=" margin: 5rem 0 2rem 0;">
{% endif %}

django-jinja href not downloading file

Hey guys I was making a page where people can download my stuff.I made a model of thta and It is succesfull in uploading that but the problem i swhen I click on the download button front end I t doesn,t download that stuff .Instead of that it downloads the copy of the page.
Here,s the models.py
class Upload(models.Model):
image = models.ImageField(upload_to = 'images',)
file = models.FileField(upload_to = 'images/%Y/%M/%d/')
name = models.CharField(max_length = 200)
def __str__(self):
return self.name
Here,s the views.py
def upload(request):
upload = Upload()
return render(request,'app/download.html',{'upload':upload})
Here,s the html file
{% block content %}
<div class="container">
<div class="download">
<p style="text-align: center;">
<img src="{{upload.image}}" alt="Image containing link to you,r success">
</p>
</div>
<h2>Click on the button below</h2>
<button class="btn btn-primary"><a href="{{upload.file.id}}" download>Yeah do it</a></button>
</div>
{% endblock %}
try
{% block content %}
<div class="container">
<div class="download">
<p style="text-align: center;">
<img src="{{upload.image}}" alt="Image containing link to you,r success">
</p>
</div>
<h2>Click on the button below</h2>
Yeah do it
</div>
{% endblock %}
Changes explained:
{{upload.file.url}} will give you the url to your uploaded file.
directly add "btn btn-primary" to your anchor tag. It'll display as button. You don't need seperate <button> tag