I want to know how to display images separated by albums onto a page in Django. So far, I've learned how to do so with the line
<img src="{% static "images/python-logo#2x.png" %}">
in my html file.
structure:
/PersonalWebsite
/static
/img
/albums
/album1
img1
/album2
img2
...etc
What I want to do is have a few album thumbnails out and upon click, all the images from the album should be displayed. I believe I would do this with an AJAX request. I am probably going to categorized these photos with tags and put names one them and other characteristics. This would be done in my models.py which I have: (though not completed)
from django.db import models
from django.contrib import admin
import os
from PersonalWebsite.settings import MEDIA_ROOT
class Album(models.Model):
title = models.CharField(max_length = 60)
def __unicode__(self):
return self.title
def get_image_by_album(self):
images = []
for root, dirs, files in os.walk(os.path.join(MEDIA_ROOT, 'albums', self.title)):
mypath = os.sep.join(os.path.join(root, file).split(os.sep[4:]))
images.append(mypath)
return images
class Tag(models.Model):
tag = models.CharField(max_length = 50)
def __unicode__(self):
return self.tag
class Image(models.Model):
title = models.CharField(max_length = 60, blank = True, null = True)
#image = models.FileField(upload_to = get_upload_file_name)
tags = models.ManyToManyField(Tag, blank = True)
albums = models.ForeignKey(Album)
width = models.IntegerField(blank = True, null = True)
height = models.IntegerField(blank = True, null = True)
created = models.DateTimeField(auto_now_add=True)
def __unicode__(self):
return self.image.name
class AlbumAdmin(admin.ModelAdmin):
search_fields = ["title"]
list_display = ["title"]
class TagAdmin(admin.ModelAdmin):
list_display = ["tag"]
class ImageAdmin(admin.ModelAdmin):
search_fields = ["title"]
list_display = ["__unicode__", "title", "created"]
list_filter = ["tags", "albums"]
admin.site.register(Album, AlbumAdmin)
admin.site.register(Tag, TagAdmin)
admin.site.register(Image, ImageAdmin)
My "get_image_by_album" parses through the albums and appends the path to "images" list. Thats as far as I've got right now =/ I also want to set up an admin so I can maintain the site easily later on. I think I am going to make a view method that will simply get the list of image paths and display it that way. I am open to suggestions! let me know what you think! I also want to set up an admin interface that would enable me to upload and edit meta data from the photos manually but I will figure out how to do so later.
I built a very simple gallery app using django-photologue. http://gallery.gentryart.us
Related
I want to display an image inside a detail view of a model, when browsing through Django Admin. I have seen other posts about displaying images in the list view of all instances of a model in Django Admin. But I'm interested in seeing the image on the page where you can edit the data.
models.py
class Label(models.Model):
label = models.TextField()
fragment = models.ForeignKey('Fragment', models.DO_NOTHING, null=True)
in_english = models.BooleanField(default=True)
validated = models.BooleanField(default=False)
def __str__(self):
return str(self.fragment)
admin.py
#admin.register(Label)
class LabelsAdmin(admin.ModelAdmin):
fields = ("label", "in_english", "validated", )
# What I tried. This is not working even after adding 'image' to the fields. I get an error.
# def image(self, obj):
# return format_html('<img src="{0}" />'.format(f"/static/fragments/{obj}.png"))
you create a method like display_image.
def display_image(self, obj):
# get image url
image_url = '<your_image_url>'
if image_url is not None:
return format_html('<img src="{}">', image_url)
return None
Add 'display_image' in fields list
fields = ("label", "in_english", "validated", 'display_image')
then make this field as a readonly
readonly_fields = ['display_image']
I'm working backend with a wagtail headless CMS and the frontend is JavaScript. I'm using a RichTextField and on the API it shows the image like this:
"<embed alt="a" embedtype="image" format="fullwidth" id="3"/>"
so because its embedtype it can't be shown on our page. I need to change the type to img with a src. I haven't tried anything because i don't even know how to start.
This is the model with the RichTextField
class ValueTagMotivation(Orderable, ClusterableModel):
"""Teams motivate why a tag was picked"""
team = ParentalKey(
TeamPage, on_delete=models.CASCADE, related_name="value_tag_motivations"
)
value_tag = models.ForeignKey(ValueTag, on_delete=models.CASCADE, related_name="+")
tagline = models.CharField(max_length=255)
motivation = RichTextField(
features=["bold", "italic", "ol", "ul", "link", "image", "embed"]
)
panels = [FieldPanel("value_tag"), FieldPanel("tagline"), FieldPanel("motivation")]
class Meta:
# a team can only pick each tag once
unique_together = (("team", "value_tag"),)
I managed to figure it out. I put
class APIRichTextSerializer(fields.CharField):
def to_representation(self, instance):
representation = super().to_representation(instance)
return expand_db_html(representation)
in my serializers.py and just called it in my main serializer
class ValueTagMotivationsSerializer(serializers.ModelSerializer):
motivation = APIRichTextSerializer()
class Meta:
model = ValueTagMotivation
fields = ['value_tag', 'tagline', 'motivation']
and now I get
"<img alt="a" class="richtext-image full-width" height="280" src="/media/images/bright-spring-view-cameo-island-260nw-10481853.width-800.png" width="475">"
I have in project two classes - Photo and Prescription inside models.py file which are related each other with foreign key. Here is part of the code:
class Photo(models.Model):
name = models.CharField(max_length=100,null=False)
photo = models.ImageField(upload_to="photos/",null=True)
def photo_tag(self):
return '<img src="/media/{0}">'.format(self.photo)
photo_tag.short_description = 'Photo of prescription'
photo_tag.allow_tags = True
class Prescription(models.Model):
description = models.CharField(max_length=100,null=True)
photo = models.ForeignKey(Photo, related_name='related_photo',null=True)
def __str__(self):
return self.description
And my Admin.py
class PhotoAdmin(admin.ModelAdmin):
list_display = ('name', 'photo_tag')
fields = ('name','photo','photo_tag')
readonly_fields = ('photo_tag',)
admin.site.register(Photo,PhotoAdmin)
class PrescriptionAdmin(admin.ModelAdmin):
list_display = ('get_photo')
fields = ('photo','description')
model = Prescription
def get_photo(self, obj):
return obj.photo.photo_tag
get_photo.short_description = 'Photo of prescription'
admin.site.register(Prescription,PrescriptionAdmin)
Question is, when I open prescriptions list instead of photo in the Photo of prescription field shows following message.
<bound method Photo.photo_tag of <Photo: Photo object>>
How real photo could be described there?
If you are going to render the image in html (which I guess you are), could you not then use ginger to display the description in a similar way to this?
<img src="{{photo.url}" title="{{photo.short_description}}" alt="{{photo.short_description}}">
Note that I included the alt for internet explorer which seems to use that instead of title.
There are few wrong issues with your approach. Your photo_tag method should be a property method, or eventually cached_property method. For displaying safely HTML code you should use the method format_html provided by Django.
Here is how I'd refactor your code:
models.py
from django.db import models
from django.utils.html import format_html
from django.utils.functional import cached_property
class Photo(models.Model):
name = models.CharField(max_length=100, null=False)
photo = models.ImageField(upload_to="photos/", null=True)
# better use blank=True instead of null=True for ImageField
#cached_property
def photo_tag(self):
if self.photo:
return format_html(
'<img src="{img}">',
img=self.photo.url
)
return None # or better return '' if you use blank=True
photo_tag.short_description = 'Photo of prescription'
class Prescription(models.Model):
description = models.CharField(max_length=100, null=True)
photo = models.ForeignKey(Photo, related_name='related_photo', null=True)
def __str__(self):
return self.description
Now you can use photo_tag as a property of Photo and bind the HTML safe in your admin.
Thanks anybody who tried to help. I figured out another solution with help of #Klaus who answered first and I am pretty sure that there is maybe much more better solutions also. Here are how I changed my code
Models.py
from django.utils.safestring import mark_safe
class Photo(models.Model):
name = models.CharField(max_length=100,null=False)
photo = models.ImageField(upload_to="photos/",null=True)
def photo_tag(self):
return mark_safe('<img src="/media/{0}">'.format(self.photo))
photo_tag.short_description = 'Photo of prescription'
photo_tag.allow_tags = True
class Prescription(models.Model):
description = models.CharField(max_length=100,null=True)
photo = models.ForeignKey(Photo, related_name='related_photo',null=True)
def __str__(self):
return self.description
Admin.py
class PhotoAdmin(admin.ModelAdmin):
list_display = ('name', 'photo_tag')
fields = ('name','photo','photo_tag')
readonly_fields = ('photo_tag',)
admin.site.register(Photo,PhotoAdmin)
class PrescriptionAdmin(admin.ModelAdmin):
list_display = ('get_photo')
fields = ('photo','description')
model = Prescription
def get_photo(self, obj):
return obj.photo.photo_tag()
get_photo.short_description = 'Photo of prescription'
admin.site.register(Prescription,PrescriptionAdmin)
Let's say I have models:
from filer.fields.image import FilerImageField()
class Image(models.Model):
name = models.CharField(max_length=128)
image = FilerImageField()
class City(models.Model):
name = models.CharField(max_length=128)
images = models.ManyToManyField(Image, blank=True)
admin.py:
class ImageAdmin(admin.ModelAdmin):
def thumb(self, obj):
return '<img src=%s />' %obj.image.icons['64']
thumb.short_description = 'Preview'
thumb.allow_tags = True
list_display = ('image', 'name', 'thumb', )
class CityAdmin(models.ModelAdmin):
filter_horizontal = ('images', )
admin.site.register(Image, ImageAdmin)
admin.site.register(City, CityAdmin)
Questions:
1. How to add "+" button in CityAdmin above m2m widget? Currently what i have:
2. Is it possible in CityAdmin m2m widget have some list display where I can see image thumbnail? Ideally like in ImageAdmin:
What I have tried:
In Image model __unicode__ function return '<img src=%s />' %self.image.icons['64'], but then in admin it just displays raw text.
I want to show image like this Django admin listview Customize Column Name.
I've checked Django Admin Show Image from Imagefield, Django - Display ImageField, Django - How can I display a photo saved in ImageField?.
This is my models.py and admin.py.
#models.py
class Movie(models.Model):
id = models.IntegerField(primary_key=True)
master_id = models.IntegerField()
url = models.CharField(max_length=100)
cover = models.CharField(max_length=100)
tittle = models.CharField(max_length=50)
duration = models.CharField(max_length=10)
click = models.IntegerField()
platform_time = models.DateTimeField()
platform_type = models.IntegerField()
entry_date = models.DateTimeField()
enable = models.IntegerField()
def image_tag(self):
return u'<img src="%s" />' % self.cover
image_tag.short_description = 'Image'
image_tag.allow_tags = True
class Meta:
managed = False
db_table = 'movie'
#admin.py
class MovieAdmin(admin.ModelAdmin):
list_display = ('id', 'master_id', 'url', 'cover', 'tittle', 'duration', 'click', 'platform_time', 'platform_type', 'entry_date', 'enable')
search_fields = ('id', 'tittle',)
list_filter = ( 'enable', )
readonly_fields = ( 'image_tag', )
Now, this is a part of my interface, there is no image_tag field. Further more, If I modify cover field to image_tag, the cover field is still not image visible.
You have to use an ImageField for cover instead of CharField and also change the image_tag return line:
cover = models.ImageField(upload_to = "images") #use the directory you want here
def image_tag(self):
return u'<img src="%s" />' % self.cover.url
Also you have to add the image_tag field to list_display.
And make sure that django can find the upload_to directory.
You have no 'image_tag' column (which contains <img...>) in list_view.
I wrote valid answer about images in django-admin listview for django 2.0.6.
Here is link on my answer:
Django: Display image in admin interface
I hope it will help someone.