jeff_hd
Si bien puedo mostrar una imagen cargada en list_display, ¿es posible hacer esto en la página por modelo (como en la página que obtiene para cambiar un modelo)?
Un modelo de muestra rápida sería:
Class Model1(models.Model):
image = models.ImageField(upload_to=directory)
El administrador predeterminado muestra la URL de la imagen cargada, pero no la imagen en sí.
¡Gracias!
Michael C. O’Connor
Seguro. En su clase de modelo, agregue un método como:
def image_tag(self):
from django.utils.html import escape
return u'<img src="https://stackoverflow.com/questions/16307307/%s" />' % escape(<URL to the image>)
image_tag.short_description = 'Image'
image_tag.allow_tags = True
y en tu admin.py
agregar:
fields = ( 'image_tag', )
readonly_fields = ('image_tag',)
para usted ModelAdmin
. Si desea restringir la capacidad de editar el campo de imagen, asegúrese de agregarlo a la exclude
atributo.
Nota: Con Django 1.8 y ‘image_tag’ solo en readonly_fields no se mostraba. Con ‘image_tag’ solo en campos, daba error de campo desconocido. Lo necesita tanto en los campos como en readonly_fields para que se muestre correctamente.
-
heyy, estaba probando la solución mencionada pero la imagen aún no aparece, lo que puedo ver es la URL de la imagen… ¿Alguien puede ayudarme?
– Anuradha
30 de julio de 2015 a las 6:13
-
@Anuradha, ¿incluiste el
image_tag.allow_tags = True
¿poco? De lo contrario, las etiquetas se escaparán y la pantalla completa<img ...>
se mostrará la etiqueta. Sin embargo, probablemente debería preguntar esto en una pregunta separada.– Michael C. O’Connor
10/08/2015 a las 18:40
-
@ MichaelC.O’Connor, sí, está funcionando ahora. Había agregado image_tag.allow_tags = Verdadero en el lugar equivocado
– Anuradha
19 de agosto de 2015 a las 11:14
-
Para versiones más nuevas de Django (1.9+) vea la respuesta de @palamunder
– Dimitris
26/09/2016 a las 22:04
-
obsoleto en Django v.1.9, @palamunder ha respondido esto.
– Vedprakash Upraity
16 mayo 2019 a las 12:30
palamunder
Además de la respuesta de Michael C. O’Connor
Tenga en cuenta que desde Django v.1.9 (actualizado, probado y trabajado hasta Django 3.0)
image_tag.allow_tags = True
está en desuso y debería usar format_html(), format_html_join() o mark_safe() en su lugar
Entonces, si está almacenando sus archivos cargados en su carpeta pública/directorio, su código debería verse así:
from django.utils.html import mark_safe
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'
y en tu admin.py agrega:
fields = ['image_tag']
readonly_fields = ['image_tag']
-
¿Por qué incluir “fields = (‘image_tag’, )”? De la prueba que elimina todos los demás campos para que no se muestren al ver el modelo con la imagen. Si omite eso, simplemente agrega el nuevo campo al final del formulario. Tampoco entiendo la obsesión con las comas finales, pero solo estoy siendo un poco quisquilloso con ese aspecto.
– Sensei
17 de octubre de 2016 a las 4:49
-
Aparentemente, los campos = (‘image_tag’, ) son necesarios solo si especifica todos los demás campos que desea. Por ejemplo, si tienes un modelo con 20 atributos, pero no quieres visualizarlos todos, puedes especificar de esa forma solo aquellos que quieras. La obsesión con las comas es solo para evitar perder una si agrega algo más después. Se ha utilizado en muchos tutoriales y libros relacionados con Django, en cualquier caso, no es necesariamente necesario. Yo, personalmente, lo encuentro útil.
– palamún
18/10/2016 a las 15:46
-
Gracias, solo quería asegurarme de que no hubiera ningún efecto secundario con la variable de campos para ciertas versiones de Django o python. Eso tiene más sentido.
– Sensei
19 de octubre de 2016 a las 2:48
-
@Sensei y palamunder, en realidad hay una diferencia con respecto a las comas finales: son requerido cuando una tupla tiene un solo objeto o no se trata como una tupla. Intentar
foo = ('a'); bar = ('b',); print foo, bar
, y verás la diferencia. De hecho, estoy sorprendido de que el ejemplo de Django funcione con un objeto que no es una colección, pero Django hace muchas cosas bien.– Juan C.
10 de noviembre de 2016 a las 19:48
-
mark_safe funciona para mí. Es importante especificar de dónde viene (desde django.utils.html import mark_safe)
– Emilio Ferreira
11 de diciembre de 2019 a las 5:28
Serjik
Se puede hacer en admin sin modificar el modelo.
from django.utils.html import format_html
@admin.register(Model1)
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',]
-
Esto es solo para la vista de lista, no para el formulario de cambio de modelo real
– Máx.
13 de febrero de 2017 a las 18:56
-
¿Cómo se agregaría texto de ayuda a esto?
– cdignam
6 de agosto de 2017 a las 18:24
-
¡Gracias! un par de mejoras y complementos: ‘
‘ para el tamaño de imagen personalizado. Use la anotación @admin.register(Model1) sobre la clase Model1Admin en lugar de la línea admin.site.register(Model1, Model1Admin) para un código un poco más limpio
– Álvaro Rodríguez Scelza
25 de abril de 2020 a las 2:21
-
Estás un poco perdiendo el punto de
format_html
haciendo el formateo real usted mismo. Esos argumentos pasados a str.format deberían pasarse en su lugar alformat_html
función– smac89
23/09/2022 a las 18:20
Venkat Kotra
Para Django 1.9
Para mostrar la imagen en lugar de la ruta del archivo en las páginas de edición, usar ImageWidget es una buena manera de hacerlo.
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="https://stackoverflow.com/questions/16307307/%s" target="_blank"><img src="https://stackoverflow.com/questions/16307307/%s" alt="https://stackoverflow.com/questions/16307307/%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)
Uso:
class IndividualBirdAdmin(ImageWidgetAdmin):
image_fields = ['thumbNail', 'detailImage']
Las imágenes aparecerán para los campos, thumbNail
y detailImage
risadinha
Con django-imagekit Puedes agregar cualquier imagen como esta:
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
-
Dos pájaros con una piedra. ¡Muchas gracias!
– Daniel García
06/09/2016 a las 20:35
-
Esto solo cambia la visualización de la lista y no la visualización de la imagen en el formulario de cambio de administrador.
– Flamm
14/10/2016 a las 14:09
-
Esta fue la forma más rápida, pude mostrar fotos en forma de cambio y vista de lista.
– Neeraj Gupta
16 de marzo de 2017 a las 12:06
Comunidad
Si bien hay algunas buenas soluciones funcionales que ya se han compartido aquí, siento que el marcado que no es de formulario, como las etiquetas de imágenes auxiliares, pertenecen a las plantillas, no se agregan a los widgets de formulario de Django ni se generan en las clases de administración del modelo. Una solución más semántica es:
Anulaciones de plantillas de administración
Nota: Aparentemente, mi reputación no es lo suficientemente alta como para publicar más de dos enlaces simples, por lo que creé anotaciones en el siguiente texto e incluí las URL respectivas al final de esta respuesta.
Desde el Documentación del sitio de administración de Django:
Es relativamente fácil anular muchas de las plantillas que utiliza el módulo de administración para generar las distintas páginas de un sitio de administración. Incluso puede anular algunas de estas plantillas para una aplicación específica o un modelo específico.
de Django django.contrib.admin.options.ModelAdmin
(comúnmente accedido bajo el espacio de nombres django.contrib.admin.ModelAdmin
) presenta una serie de posibles rutas de plantilla para Cargador de plantillas de Django en orden de lo más específico a lo menos. Este fragmento fue copiado directamente 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)
Por lo tanto, considerando la documentación de anulación de la plantilla de administración de Django mencionada anteriormente y las rutas de búsqueda de plantillas, supongamos que uno ha creado una aplicación “artículos” en la que se define una clase de modelo “Artículo”. Si uno quiere anular o extender solo el formulario de cambio de sitio de administración de Django predeterminado para el modelo articles.models.Article
se ejecutarían los siguientes pasos:
- Cree una estructura de directorio de plantilla para el archivo de anulación.
- Aunque la documentación no lo menciona, el cargador de plantillas buscará primero en los directorios de aplicaciones si
APP_DIRS
1 se establece enTrue
. - Debido a que uno quiere anular la plantilla del sitio de administración de Django por etiqueta de aplicación y por modelo, la jerarquía de directorios resultante sería:
<project_root>/articles/templates/admin/articles/article/
- Aunque la documentación no lo menciona, el cargador de plantillas buscará primero en los directorios de aplicaciones si
- Cree los archivos de plantilla en su nueva estructura de directorios.
- Solo se debe anular el formulario de cambio de administrador, así que cree
change_form.html
. - El camino final y absoluto será
<project_root>/articles/templates/admin/articles/article/change_form.html
- Solo se debe anular el formulario de cambio de administrador, así que cree
- Anule por completo o simplemente amplíe la plantilla de formulario de cambio de administrador predeterminada.
- No pude encontrar ninguna información en la documentación de Django sobre los datos de contexto disponibles para las plantillas del sitio de administración predeterminadas, por lo que me vi obligado a mirar el código fuente de Django.
- Plantilla de formulario de cambio predeterminada: github.com/django/django/blob/master/django/contrib/admin/templates/admin/change_form.html
- Algunas de las definiciones relevantes del diccionario de contexto se pueden encontrar en
django.contrib.admin.options.ModelAdmin._changeform_view
ydjango.contrib.admin.options.ModelAdmin.render_change_form
- No pude encontrar ninguna información en la documentación de Django sobre los datos de contexto disponibles para las plantillas del sitio de administración predeterminadas, por lo que me vi obligado a mirar el código fuente de Django.
Mi solución
Suponiendo que el nombre de mi atributo ImageField en el modelo sea “archivo”, la anulación de mi plantilla para implementar vistas previas de imágenes sería similar a esto:
{% 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
parece ser la instancia del modelo a partir de la cual se generó ModelForm. Aparte, normalmente no uso CSS en línea, pero no valía la pena un archivo separado para una sola regla.
Fuentes:
- docs.djangoproject.com/en/dev/ref/settings/#app-dirs
-
Dos pájaros con una piedra. ¡Muchas gracias!
– Daniel García
06/09/2016 a las 20:35
-
Esto solo cambia la visualización de la lista y no la visualización de la imagen en el formulario de cambio de administrador.
– Flamm
14/10/2016 a las 14:09
-
Esta fue la forma más rápida, pude mostrar fotos en forma de cambio y vista de lista.
– Neeraj Gupta
16 de marzo de 2017 a las 12:06
Dettlaff
Estaba tratando de resolverlo yo mismo y esto es lo que se me ocurrió
@admin.register(ToDo)
class ToDoAdmin(admin.ModelAdmin):
def image_tag(self, obj):
return format_html('<img src="{}" width="auto" height="200px" />'.format(obj.img.url))
image_tag.short_description = 'Image'
list_display = ['image_tag']
readonly_fields = ['image_tag']
-
así no es como
format_html
se supone que debe usarse. Leer los documentos– smac89
23/09/2022 a las 19:35