unable to display image using jinja - django

I created a separate model for users to upload a profile pic.
models.py
class Image(models.Model):
profilepic = models.ImageField(upload_to='images/', null = True)
def __str__(self):
return self.title
html
<img src="/images/{{ image.profilepic }}"/>
all I am getting back is a empty canvas with an image icon
I should note the images are uploading to the folder just not displaying

I think need to add .url like this
<img src="/images/{{ image.profilepic.url }}"/>

Related

Django admin - creating image admin models

I have looked through the posts but didn't find what I'm looking for, this is why I'm asking.
The goal is to be able to create image galleries in the admin, then to upload images and to choose in which (already created) gallery to be uploaded and after that, when creating a post (for example) to have a field which to access the gallery model and to choose images to be used in a carousel gallery in the said post.
For example, I'm creating a post in a travel blog and would like to add few images from the trip I had to use in a carousel.
I hope I have explained the goal understandable and someone to be able to show me a way or to point in the right direction
If there are any first party solutions, I'd be very happy
Please, since I'm new in django link a more detailed answer or tutorial or explain for a newbie
Heres answer for your idea..
change your models.py like this
class Carousel(models.Model):
carousel_name = models.CharField(max_length=50)
def __str__(self):
return self.carousel_name
class Photo(models.Model):
carousel = models.ForeignKey(Carousel, on_delete=models.CASCADE)
image =models.ImageField(upload_to="carousel_image", height_field=None, width_field=None, max_length=None)
Then in your Views.py:
from django.views.generic import DetailView
from .models import Carousel, Photo
class CarouselView(DetailView):
model = Carousel
template_name = 'carousel.html'
Now in your admin.py:
from .models import Carousel, Photo
class PhotoInline(admin.TabularInline):
model= Photo
extra= 3
class CarouselAdmin(admin.ModelAdmin):
inlines=[PhotoInline]
admin.site.register(Carousel, CarouselAdmin)
Now make your urlpattern to fetch pk as kwargs for image to be loaded like this:
urlpatterns = [
path('<int:pk>/', CarouselView.as_view())
]
Finally in your template:
render as:
<!-- The slideshow -->
<div class="carousel-inner">
{% for photo in carousel.photo_set.all %}
<div class="carousel-item active">
<img src="{{ photo.image.url }}" alt="Image {{forloop.counter}}" width="1100" height="500">
</div>
{% endfor %}
</div>
Now the gallery should work as you have expected it to.
Hope You get what you are searching for.😊

Django - How to return to default image after users delete their uploaded image?

So I originally had the user create a post in admin and be able to leave image field blank and Django would set a default image.
My problem is;
If a user uploads an image, then deletes the image in admin, I get an error: The 'image' attribute has no file associated with it. when accessing solo.html in browser.
How can I make the default image reappear and specifically come from static folder?
My code:
settings.py
STATIC_URL = '/static/'
STATIC_DIRS = os.path.join(BASE_DIR, 'static')
models.py
# FIXME: If default image is changed to user's upload but then deleted. Make default image reappear.
# Recipe Field
class Recipe(models.Model):
title = models.CharField(max_length=200)
image = models.ImageField(upload_to='recipes/images/', blank=True)
def get_image(self):
if not self.image:
return f'{settings.STATIC_URL}default.png'
return self.image.url
solo.html
<h2>{{ recipe.title }}</h2>
<h3>{{ recipe.category }}</h3>
<h3>{{ recipe.meal }}</h3>
<img src="{{ recipe.image.url }}">
I'm just starting with Django so I apologize in advance if it's all a mess.
Thank you in advance!
What's happening is that the file itself is being deleted, but recipe.image is not being set to None.

django cutom image name on upload

I need create a image upload with django, the problem is, django always saving in a global project(called linkdump) folder, I want save it on the project folder(linktracker).
setting.py:
STATIC_URL = '/static/'
model:
class Link(models.Model):
link_description = models.CharField(max_length=200)
link_url = models.CharField(max_length=200)
link_image = models.ImageField(upload_to= './static/')
def __str__(self):
return self.link_description
class Admin:
pass
now in the view:
<img src="{% static link.link_image %}" alt="{{ link.link_description }}">
it returns
http://127.0.0.1:8000/static/static/o-BLUE-LIGHT-SLEEP-facebook.jpg
and the upload is in the project folder(linkdump), not inside the app.
You can specify a function to return a custom path for the ImageField:
def get_upload_path(instance, filename):
return 'your/custom/path/here'
class Link(models.Model):
. . .
link_image = models.ImageField(upload_to=get_upload_path)
Now you can use information from the model instance to build up the path to upload to.
Additionally, you don't want to use the {% static %} template tag to specify the path to the image. You would just use the .url property of the field:
<img src="{{ link.link_image.url }}" alt="{{ link.link_description }}" />

Prevent users from seeing other user's uploaded pictures

I have a django applications that uses multi-users. Users can upload pictures on the system.I have created a picture model that has a foreignKey of a users to know which user uploaded which picture.
class Picture(models.Model):
picture = models.ImageField(upload_to='pictures')
uploader = models.ForeignKey(User)
#other specific fields like date etc
I have set up my settings file to use the MEDIA_URL and MEDIA_ROOT
settings.py
MEDIA_URL ='/media/'
MEDIA_ROOT = 'path/to/media/'
So I am able to access a picture in www.mydomain.com/media/pictures/picture.jpg. But I guess having a common MEDIA_ROOT means that any user can see this picture right?Not just the user who uploaded it. In my webpages I use
<img src={{image.picture}}>
to show images of a user. How can I prevent a user from seeing a picture a different user has uploaded(a forbidden message)? Can this be done on setup?
Your view function probably looks something like this:
#login_required
def theview(request):
...
image = Picture.objects.get(*args)
...
return render(request, 'template', {'image': image})
The point being that you can easily only pass the image along if it's the logged in user that have uploaded it. For instance
image = get_object_or_404(Picture, uploader=request.user, other_filters)
Or even
image = Picture.objects.get(*args)
image = image if image.uploader == request.user else None
Then in the django template
{% if image %}
<img ....>
{% endif %}
You can try like this:
in views:
def allpicture(request):
.....
#for all pictures
images= Picture.objects.filter(uploader=request.User)
return render(request, '/sometemplate', {'images': images})
def onepicture(request, pic_id):
....
#for one picture
image= Picture.objects.filter(id= pic_id, uploader=request.User) #url for this view should be like url(r'^pictures/(?P<pic_id>\d+)/$'
render render(request, '/sometemplate', {'image': image})

ImageField: save filename only

I have model with ImageFile field:
def upload_course_cover(object, filename):
return '/media/courses/%s_%s' % (Course.objects.aggregate(Max('id'))['id__max'] + 1, filename)
class Course(models.Model):
# ...
cover = models.ImageField(upload_to=upload_course_cover, blank=True)
When the image is saved, into cover field will be writen full image path /media/courses/id_filename.ext, but I want store only image name id_filename.ext.
How to do it?
You cannot change what it stores in the database - unless you create your own custom field; or use a CharField.
If you just want to display the filename:
import os
c = Course.objects.get(pk=1)
fname = os.path.basename(c.cover.name)
# if cover's name is /hello/foo/bar.html
# fname will be bar.html
However, since you have image field - you can get lots of benefits out of it, for example - to get the URL to display the image in an img tag:
<img src="{{ c.cover.url }}"
alt="cover image for {{ c.name }}"
/>
You can also get some other benefits, for example:
class Course(models.Model):
# ....
cover_height = models.IntegerField()
cover_width = models.IntegerField()
cover = models.ImageField(upload_to=upload_course_cover,
height_field=cover_height,
width_field=cover_width,
# your other options...
)
Now you can do:
<img src="{{ c.cover.url }}" height="{{ c.cover_height }}" width="{{ c.cover_width }}">
"When the image is saved, into cover field will be writen full image path /media/courses/id_filename.ext"
To be precise, this is not true. Only the relative path from your MEDIA_ROOT is saved in the database. See https://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.FileField.upload_to
(ImageField has the same properties as FileField)
To save only the filenames, you could
Add a new CharField to store the names
Use os.split() to get just the filename when called