Bien que je puisse montrer une image téléchargée dans list_display, est-il possible de le faire sur la page par modèle (comme dans la page que vous obtenez pour changer un modèle)?
Un modèle d'échantillon rapide serait:
Class Model1(models.Model):
image = models.ImageField(upload_to=directory)
L'administrateur par défaut affiche l'url de l'image téléchargée mais pas l'image elle-même.
Merci!
Sûr. Dans votre classe de modèle, ajoutez une méthode comme:
def image_tag(self):
from Django.utils.html import escape
return u'<img src="%s" />' % escape(<URL to the image>)
image_tag.short_description = 'Image'
image_tag.allow_tags = True
et dans votre admin.py
ajouter:
fields = ( 'image_tag', )
readonly_fields = ('image_tag',)
à votre ModelAdmin
. Si vous souhaitez restreindre la possibilité de modifier le champ d'image, assurez-vous de l'ajouter à l'attribut exclude
.
Remarque: Avec Django 1.8 et 'image_tag' uniquement dans readonly_fields, il ne s'affichait pas. Avec 'image_tag' uniquement dans les champs, il donnait une erreur de champ inconnu. Vous en avez besoin à la fois dans les champs et dans readonly_fields afin de s'afficher correctement.
En plus de la réponse de Michael C. O'Connor
Notez que dans Django v.1.9
image_tag.allow_tags = True
est obsolète et vous devez utiliser format_html (), format_html_join () ou mark_safe () à la place
Donc, si vous stockez vos fichiers téléchargés dans votre dossier public/répertoire, votre code devrait ressembler à ceci:
Class Model1(models.Model):
image = models.ImageField(upload_to=directory)
def image_tag(self):
return mark_safe('<img src="/directory/%s" width="150" height="150" />' % (self.image))
image_tag.short_description = 'Image'
et dans votre admin.py ajoutez:
fields = ['image_tag']
readonly_fields = ['image_tag']
Cela peut être fait en admin sans modifier le modèle
from Django.utils.html import format_html
class Model1Admin(admin.ModelAdmin):
def image_tag(self, obj):
return format_html('<img src="{}" />'.format(obj.image.url))
image_tag.short_description = 'Image'
list_display = ['image_tag',]
admin.site.register(Model1, Model1Admin)
Pour Django 1.9 Pour afficher l'image au lieu du chemin du fichier dans les pages d'édition, utiliser ImageWidget est une bonne façon de le faire.
from Django.contrib.admin.widgets import AdminFileWidget
from Django.utils.translation import ugettext as _
from Django.utils.safestring import mark_safe
from Django.contrib import admin
class AdminImageWidget(AdminFileWidget):
def render(self, name, value, attrs=None):
output = []
if value and getattr(value, "url", None):
image_url = value.url
file_name = str(value)
output.append(u' <a href="%s" target="_blank"><img src="%s" alt="%s" /></a> %s ' % \
(image_url, image_url, file_name, _('Change:')))
output.append(super(AdminFileWidget, self).render(name, value, attrs))
return mark_safe(u''.join(output))
class ImageWidgetAdmin(admin.ModelAdmin):
image_fields = []
def formfield_for_dbfield(self, db_field, **kwargs):
if db_field.name in self.image_fields:
request = kwargs.pop("request", None)
kwargs['widget'] = AdminImageWidget
return db_field.formfield(**kwargs)
return super(ImageWidgetAdmin, self).formfield_for_dbfield(db_field, **kwargs)
tilisation:
class IndividualBirdAdmin(ImageWidgetAdmin):
image_fields = ['thumbNail', 'detailImage']
Les images s'affichent pour les champs, thumbNail
et detailImage
Avec Django-imagekit vous pouvez ajouter n'importe quelle image comme celle-ci:
from imagekit.admin import AdminThumbnail
@register(Fancy)
class FancyAdmin(ModelAdmin):
list_display = ['name', 'image_display']
image_display = AdminThumbnail(image_field='image')
image_display.short_description = 'Image'
readonly_fields = ['image_display'] # this is for the change form
Bien qu'il existe de bonnes solutions fonctionnelles déjà partagées ici, je pense que le balisage non formel, comme les balises d'image auxiliaires, appartient aux modèles, n'est pas collé à Django widgets de formulaire ou généré dans le modèle classes admin. Une solution plus sémantique est:
Remarque: Apparemment, ma réputation n'est pas assez élevée pour publier plus de deux liens simples, j'ai donc créé des annotations dans le texte suivant et inclus les URL respectives au bas de cette réponse.
Depuis la documentation du site d'administration Django :
Il est relativement facile de remplacer la plupart des modèles utilisés par le module d'administration pour générer les différentes pages d'un site d'administration. Vous pouvez même remplacer certains de ces modèles pour une application spécifique ou un modèle spécifique.
Django's Django.contrib.admin.options.ModelAdmin
(généralement accessible sous l'espace de noms Django.contrib.admin.ModelAdmin
) présente une série de chemins de modèles possibles vers chargeur de modèles de Django dans l'ordre du plus spécifique au moins. Cet extrait a été copié directement à partir de Django.contrib.admin.options.ModelAdmin.render_change_form
:
return TemplateResponse(request, form_template or [
"admin/%s/%s/change_form.html" % (app_label, opts.model_name),
"admin/%s/change_form.html" % app_label,
"admin/change_form.html"
], context)
Par conséquent, compte tenu de la documentation de remplacement du modèle d'administration et des chemins de recherche du modèle précités Django Django), supposons que l'on ait créé une application "articles" dans laquelle est définie une classe de modèle "Article". Si l'on veut remplacer ou étendre seulement la forme par défaut Django changement de site d'administration pour le modèle articles.models.Article
, on exécuterait les étapes suivantes:
APP_DIRS
1 est défini sur True
.<project_root>/articles/templates/admin/articles/article/
change_form.html
.<project_root>/articles/templates/admin/articles/article/change_form.html
Django.contrib.admin.options.ModelAdmin._changeform_view
et Django.contrib.admin.options.ModelAdmin.render_change_form
En supposant que mon nom d'attribut ImageField sur le modèle est "fichier", mon remplacement de modèle pour implémenter des aperçus d'image serait similaire à ceci:
{% extends "admin/change_form.html" %}
{% block field_sets %}
{% if original %}
<div class="aligned form-row">
<div>
<label>Preview:</label>
<img
alt="image preview"
src="/{{ original.file.url }}"
style="max-height: 300px;">
</div>
</div>
{% endif %}
{% for fieldset in adminform %}
{% include "admin/includes/fieldset.html" %}
{% endfor %}
{% endblock %}
original
semble être l'instance de modèle à partir de laquelle le ModelForm a été généré. En passant, je n'utilise généralement pas de CSS en ligne mais cela ne valait pas un fichier séparé pour une seule règle.
C'est comment cela a fonctionné pour Django 2.1 sans modifier models.py
:
Dans votre modèle Hero
, vous avez un champ d'image .:
headshot = models.ImageField(null=True, blank=True, upload_to="hero_headshots/")
Vous pouvez le faire comme ceci:
@admin.register(Hero)
class HeroAdmin(admin.ModelAdmin, ExportCsvMixin):
readonly_fields = [..., "headshot_image"]
def headshot_image(self, obj):
return mark_safe('<img src="{url}" width="{width}" height={height} />'.format(
url = obj.headshot.url,
width=obj.headshot.width,
height=obj.headshot.height,
)
)
Mise à jour Django 2.1 pour Venkat Kotra réponse . La réponse fonctionne très bien sur Django 2.0.7 et ci-dessous. Mais donne une erreur au serveur 500 (si DEBUG=False
) Ou donne
render() got an unexpected keyword argument 'renderer'
La raison en est qu'en Django 2.1: Support for Widget.render() methods without the renderer argument is removed.
Donc, param renderer
est maintenant obligatoire. Nous devons mettre à jour la fonction render()
de AdminImageWidget
pour inclure param renderer
. Et cela doit être après attrs
(avant kwargs
si vous l'avez):
class AdminImageWidget(AdminFileWidget):
def render(self, name, value, attrs=None, renderer=None):
output = []
if value and getattr(value, "url", None):
image_url = value.url
file_name = str(value)
output.append(u' <a href="%s" target="_blank"><img src="%s" alt="%s" /></a> %s ' % \
(image_url, image_url, file_name, _('Change:')))
output.append(super(AdminFileWidget, self).render(name, value, attrs, renderer))
return mark_safe(u''.join(output))