Django - add image to list display in django admin - python

Please help me. I gave up. I am trying to add additional field to my django admin. I would like to insert image thumbnail there. This is part of my admin.py:
class SiteAdmin(admin.ModelAdmin):
list_display = ('is_active', 'name', 'description', 'keywords', 'date')
fields = ('name', 'url', 'category', 'subcategory', 'category1',
'subcategory1', 'description',
'keywords', 'date', 'group', 'email', 'is_active')
readonly_fields = ('date',)
list_display_links = ('name',)
list_filter = ('is_active',)
actions = [activate_sites, deactivate_sites]
I wolud like to add 'image' to list_display. Images are generating by thumbalizr. I have a method in models.py:
class Site(models.Model):
category = models.ForeignKey('Category')
subcategory = ChainedForeignKey(
'SubCategory',
chained_field='category',
chained_model_field='category',
show_all=False,
auto_choose=True,
blank=True, null=True, default=None)
name = models.CharField(max_length=70, verbose_name="Tytuł")
description = models.TextField(verbose_name="Opis")
keywords = MyTextField(max_length=100, verbose_name="Słowa kluczowe")
date = models.DateTimeField(default=datetime.now, editable=False)
url = models.URLField()
is_active = models.BooleanField(default=False)
category1 = models.ForeignKey('Category', related_name='category', blank=True, null=True, default=None)
subcategory1 = ChainedForeignKey(
'SubCategory',
chained_field='category1',
chained_model_field='category',
related_name='subcategory',
show_all=False,
auto_choose=True, blank=True, null=True)
group = models.CharField(max_length=10, choices=(('podstawowy', 'podstawowy'),
('premium', 'premium')), default='podstawowy',
help_text="<div id='group'><ul><li>You can add site to 2 <b>categories</b></li></ul></div>")
email = models.EmailField(help_text='Podaj adres email')
def get_absolute_url(self):
return reverse('site', args=[str(self.category.slug),
str(self.subcategory.slug), str(self.id)])
def get_thumb(self):
host = urlparse(self.url).hostname
if host.startswith('www.'):
host = host[4:]
thumb = 'https://api.thumbalizr.com/?url=http://' + host + '&width=125'
return thumb
It is get_thumb(). How can I take image to every site and put in in my django admin page? Should I add additional field to my Site model? I don't want to store images on my server - they are directly from thumbalizr.

You should add a method into your modeladmin class. Then you can add this method into your field list.
class SiteAdmin(admin.ModelAdmin):
list_display = [..., 'thumb']
...
...
def thumb(self, obj):
return "<img src='{}' width='20' height='20' />".format(obj.get_thumb())
thumb.allow_tags = True
thumb.__name__ = 'Thumb'
https://docs.djangoproject.com/en/1.10/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_display

I was solving this problem in latest django 2.0.6. I wanted to achiave to have image thubnail and some more details in listview in django-admin.
I post answer here:
Django: Display image in admin interface

You can create thumb column by defining thumb() and by assigning thumb() to list_display as shown below:
# "admin.py"
from django.contrib import admin
from .models import Site
from django.utils.html import format_html
#admin.register(Site)
class SiteAdmin(admin.ModelAdmin):
list_display = (
'is_active',
'name',
'description',
'keywords',
'date',
'thumb' # Here
)
# ...
def thumb(self, obj): # Here
return format_html(
f'''<a href="{obj.get_thumb()}" target="_blank">
<img
src="{obj.get_thumb()}" alt="{obj.get_thumb()}"
width="50" height="50"
style="object-fit: cover;"
/>
</a>''')

Related

Change verbose name and help text on Django Admin Page

i'm developing a django site deployed via Nginx and PostgreSQL.
I did some changes to my models.py and admin.py pages to correct a field.
Yet this change is not being shown in my Django admin page, it's still with the old field names regardless of the change in my models.py folder.
Here's the models.py and admin.py sections of code
models.py
title = models.CharField(max_length=100, help_text="Titulo del Proyecto", verbose_name="Titulo")
subtitle = models.CharField(max_length=100, help_text="Subtitulo", verbose_name="Subtitulo")
image = models.ImageField(upload_to='media/images',blank=True, help_text="Imagen del Proyecto", verbose_name="Imagen")
slug = models.SlugField(max_length=100, help_text="No tocar", verbose_name="Slug")
description = models.TextField(help_text="Descripcion del Proyecto", verbose_name="Descripcion")
date = models.DateField()
video_url = models.CharField(max_length=200, blank=True,help_text='Url del video ', verbose_name='Video URL')
source = models.ForeignKey('Source', on_delete=models.CASCADE,blank=True, help_text='Youtube o Vimeo o NONE si no hay video',verbose_name='Source')
category = models.ForeignKey('Category', on_delete=models.SET_NULL, null=True, help_text='Categoria del projecto', verbose_name='Categoria')
admin.py
class ProjectAdmin(admin.ModelAdmin):
pass
list_display = ('title', 'date', 'category', 'source')
list_filter = ('date', 'category', 'source')
search_fields = ('title', 'description')
ordering = ['-date', 'title']
date_hierarchy = 'date'
fieldsets = (
(None, {
'fields': ('title','subtitle', 'description', 'image', 'date', 'video_url', 'source', 'category', 'slug')
}),
)
prepopulated_fields = {'slug': ('title',)}
Please check you question, your code is not completely there, or it from different project: for example, label in model for category is "Categoria", field label on the admin panel is "Catégorle".
I can imagine, that you work with lazy translations. In this case you should change translations for 'label' and 'help_text' and not to do something with models.
Other case is, you Admin form is overridden. There you can change labels and help text too.

how to add a button/on click action in Django admin page model

I have a model where I have list of servers...
Here is my model:
class Ipaddress(models.Model):
ip_address=models.CharField("Ip address",max_length=20)
device_type= models.ForeignKey("DeviceType", on_delete=models.CASCADE)
slug = models.SlugField(unique=True)
machine_name=models.CharField("Machine Name",max_length=500)
user=models.CharField("User",max_length=200)
department= models.ForeignKey("Department", on_delete=models.CASCADE)
location= models.ForeignKey("Location", on_delete=models.CASCADE)
updated = models.DateField("Date Updated",null=True)
note =models.TextField()
class Meta:
verbose_name = 'IP Management'
def __str__(self):
return self.ip_address[:50]
I want to add ping server action for every model record and store "Yes" if it revived any response. Here is admin page:
from django.contrib import admin
from pages.models import Ipaddress, DeviceGroup, Location,Department,
from django_admin_listfilter_dropdown.filters import DropdownFilter, RelatedDropdownFilter
class DepartmentAdmin(admin.ModelAdmin):
search_fields = ['name']
class LocationAdmin(admin.ModelAdmin):
search_fields = ['description']
list_display =('description',)
class IpaddressAdmin(admin.ModelAdmin):
prepopulated_fields = {'slug': ('ip_address',)}
search_fields = ('ip_address', 'machine_name')
list_display = ('ip_address', 'device_type', 'machine_name', 'user', 'department','location','updated',)
list_display_links =('ip_address', 'device_type', 'machine_name', 'user', 'department','location','updated',)
autocomplete_fields = ['location','department',]
list_filter = (
('user', DropdownFilter),
('department', RelatedDropdownFilter),
('location', RelatedDropdownFilter),
('device_type', RelatedDropdownFilter),
)
I am thinking to add a button to pop up a small dialog box from where user will confirm ping. Need some help how I can do that?

Django Admin how to change text in relations field

I have the following code:
models.py
from django.db import models
from parler.models import TranslatableModel, TranslatedFields
class Federation(TranslatableModel):
translations = TranslatedFields(
name = models.CharField('name', max_length=50)
)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Athlete(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
federation = models.ForeignKey('Federation', on_delete=models.SET_NULL, null=True)
height = models.IntegerField();
weight = models.IntegerField();
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
admin.py
from django.contrib import admin
from parler.admin import TranslatableAdmin
from .models import Athlete, Federation
class AthleteAdmin(admin.ModelAdmin):
list_display = ['first_name', 'last_name', 'height', 'weight', 'get_federation_name']
fields = ['first_name', 'last_name', 'height', 'weight', 'federation']
def get_federation_name(self, obj):
obj.federation.set_current_language('en')
return obj.federation.name
get_federation_name.short_description = 'Federation'
class FederationAdmin(TranslatableAdmin):
search_fields = ['translations__name']
list_display = ['name']
fields = ['name']
admin.site.register(Federation, FederationAdmin)
admin.site.register(Athlete, AthleteAdmin)
The federation field is shown as a list but the text in the select menu is shown as "Federation object." For the list, I created a function to fetch the data from related Federation model's translation relation. I want to do the same with the form fields. If I get this to work in form fields without a function, I will also change the list display to work the same way.
I am new to Python and Django (first time) and I can't seem to find a solution to this problem.
Thank you!
By default it uses the __str__() method of the object. So the easiest way to change this is to set this method. For instance:
class Federation(models.Model):
...
def __str__(self):
return "{0} ({1})".format(self.translation, self.created_at)
Another way — if you don't want to override the __str__ method — would be to override the label_from_instance of the form Field itself. But it's more tricky.
def _federation_label_from_instance(self, obj):
return "{0} ({1})".format(obj.translation, obj.created_at)
class AthleteAdmin(admin.ModelAdmin):
...
def formfield_for_foreignkey(self, db_field, request, **kwargs):
formfield = super().form_field(db_field, request, **kwargs)
if db_field.name == 'federation':
formfield.label_from_instance = _federation_label_from_instance
return formfield

ModelChoiceField initial value from db

I tried to find out how to set the initial value of a ModelChoiceField, I found many answers to this question but I don't really get them. I understand that I can set "initial" when calling the form in admin.py but then a model instance is mentioned and I am lost.
This is my models.py
class Articles(models.Model):
headline = models.CharField('Rubrik', max_length=200)
category = models.CharField('Kategori', max_length=200, blank=True)
extract = models.TextField('Utdrag')
image = ImageField('Bild', upload_to='articles', blank=True, default="")
text = RichTextUploadingField('Text', blank=True, default="")
added = models.DateTimeField('Publicerad', default=timezone.now, blank=True)
updated = models.DateTimeField('Uppdaterad',auto_now=True)
frontpage = models.BooleanField('Visa på startsida', default=True)
active = models.BooleanField('Aktiv', default=False)
def save(self, *args, **kwargs):
if self.added is None:
self.added = timezone.now
super(Articles, self).save(*args, **kwargs)
def __unicode__(self):
return '%s' % (self.headline)
class Meta:
verbose_name = "artikel"
verbose_name_plural = "Artiklar"
This is my forms.py
class ArticleForm(forms.ModelForm):
category = forms.ModelChoiceField(queryset=Menu.objects.order_by('name').filter(category=True))
This is my admin.py
class ArticlesAdmin(admin.ModelAdmin):
form = ArticleForm
list_display = ('headline','category', 'extract', 'image', 'added', 'updated', 'frontpage', 'active')
admin.site.register(Articles, ArticlesAdmin)
When I edit the article in the admin section I want the stored value of the category to be the initial value for the ModelChoiceField. Do you get what I mean?
In admin.py there should be something like:
form = ArticleForm(initial = {'category': instance.something})
*EDIT: I added ForeignKey as suggested
category = models.ForeignKey(Menu)
and admin.py looks like this:
class ArticlesAdmin(admin.ModelAdmin):
form = ArticleForm
list_display = ('headline','category', 'extract', 'image', 'added', 'updated', 'frontpage', 'active')
And now it's working as expected!
This code should work:
form = ArticleForm(initial = {'category': pk})
pk is the stored value, pk = primary key

Django Admin Drag and Drop

Looking for some guidance because I'm entering new territory here in terms of my Django experience. I'm writing a reprographics request app so have created a couple of models:
class Job(models.Model):
id = models.AutoField(primary_key=True) # AutoField?
class Resource(models.Model):
id = models.AutoField(primary_key=True) # AutoField?
job = models.ForeignKey(Job)
file = models.FileField(upload_to="repro/")
The admin view includes the resource as inline
class ResourceInline(admin.TabularInline):
model = Resource
extra = 0
class JobAdmin(admin.ModelAdmin):
model = Job
list_display = ['requestedby','account','requestdate','requireddate','noofsides','noofcopies']
list_filter = ['requireddate']
search_fields = ['requestedby','account']
form = JobForm
fieldsets = [
(None, {'fields': ['requestedby','account','requestdate','requireddate','noofsides','noofcopies'] }),
('Requirements', {'fields': ['color','sided','paper','finishing']}),
('Additional Information', {'fields': ['additionalinfo']}),
]
inlines = [ResourceInline]
admin.site.register(Job,JobAdmin)
I'm planning to use dropzone.js and have got myself a change_form.html that I can customise but at this point I'm a bit lost. How can I replace the inline with my dropzone area and get it working?
Thanks for any help or pointers.
Chris
Use adminsortable2 to drag and drop in Django Admin. This is the github link.
So in you case, the code with adminsortable2 is this below.
"models.py":
from django.db import models
class Job(models.Model):
id = models.AutoField(primary_key=True)
my_order = models.PositiveIntegerField(default=0, blank=False, null=False)
class Meta:
ordering = ['my_order']
class Resource(models.Model):
id = models.AutoField(primary_key=True)
job = models.ForeignKey(Job)
file = models.FileField(upload_to="repro/")
my_order = models.PositiveIntegerField(default=0, blank=False, null=False)
class Meta:
ordering = ['my_order']
"admin.js":
from django.contrib import admin
from adminsortable2.admin import SortableAdminMixin, SortableInlineAdminMixin
from .models import Job, Resource
class ResourceInline(SortableInlineAdminMixin, admin.TabularInline):
model = Resource
extra = 0
#admin.register(Job)
class JobAdmin(SortableAdminMixin, admin.ModelAdmin):
list_display = ['requestedby','account','requestdate','requireddate','noofsides','noofcopies']
list_filter = ['requireddate']
search_fields = ['requestedby','account']
form = JobForm
fieldsets = [
(None, {'fields': ['requestedby','account','requestdate','requireddate','noofsides','noofcopies'] }),
('Requirements', {'fields': ['color','sided','paper','finishing']}),
('Additional Information', {'fields': ['additionalinfo']}),
]
inlines = [ResourceInline]
Then, run this command below after writing the code above to save your sorting:
python manage.py reorder <app.model>
So, in your case, I don't know your app name so if your app name is "work" and I know your model names "Job" and "Resource" so run this command below to save your sorting:
python manage.py reorder work.Job work.Resource

Categories

Resources