The image is not displayed in the template, in the img tag. The django documentation is very poor on this topic. I have also followed some tutorials but it doesn't work either. The rest of the application works perfectly, I only have to fix this. This is my project: Structure of the static and media folders:
├───.settings
├───catalogo
│ ├───migrations
│ │ └───__pycache__
│ └───__pycache__
├───media
│ └───fotos
│ ├───articulos
│ └───libros
├───plantillas
│ ├───catalogo
│ └───registration
├───static
│ ├───admin
│ │ ├───css
│ │ │ └───vendor
│ │ │ └───select2
│ │ ├───fonts
│ │ ├───img
│ │ │ └───gis
│ │ └───js
│ │ ├───admin
│ │ └───vendor
│ │ ├───jquery
│ │ ├───select2
│ │ │ └───i18n
│ │ └───xregexp
│ ├───css
│ ├───js
│ └───media
Project Settings:
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
Models:
class FotoArt(models.Model):
nombre = models.CharField(max_length=50)
foto = models.ImageField(upload_to='fotos/articulos/',
null=True, blank=True)
class Meta:
ordering = ['nombre']
verbose_name = _('Foto Artículo')
verbose_name_plural = _('Fotos Artículos')
def __str__(self):
return self.nombre
def get_absolute_url(self):
return reverse('detalle-fotoArt', args=
[str(self.id)])
class ArtMixin(models.Model):
class Meta:
abstract = True
ordering = ["titulo"]
AÑO_CHOICES = []
for r in range(1975, (datetime.datetime.now().year+1)):
AÑO_CHOICES.append((r,r))
NORMAL = 'NR'
BUENO = 'BN'
NUEVO = 'NV'
ESTADO_CHOICES = [
(NORMAL, 'Normal, con señales de uso'),
(BUENO, 'Buen estado, como nuevo'),
(NUEVO, 'Nuevo'),
]
titulo = models.CharField(max_length=200)
precio = models.PositiveSmallIntegerField()
estado = models.CharField(
max_length = 2,
choices = ESTADO_CHOICES,
default = BUENO,
)
publicado_URLs = models.ManyToManyField(Publicacion,
blank=True)
descripcion = models.TextField(null=True, blank=True)
def __str__(self):
return self.titulo
class Articulo(ArtMixin):
año_compra = models.PositiveSmallIntegerField(choices =
ArtMixin.AÑO_CHOICES)
fotos = models.ManyToManyField(FotoArt, blank=True)
class Meta:
verbose_name = _('Artículo')
verbose_name_plural = _('Artículos')
def get_absolute_url(self):
return reverse('detalle-art', args=[str(self.id)])
The views:
class DetalleFotoArt(generic.DetailView):
model = FotoArt
context_object_name = "fotoArt"
template_name = 'catalogo/detalle_fotoArt.html'
class FotoArtCrear(LoginRequiredMixin, CreateView):
model = FotoArt
fields = '__all__'
Templates:
detalle_fotoArt.html
{% extends 'catalogo/base.html' %}
{% block content %}
<h1>Foto Artículo: {{ fotoArt.nombre }}</h1>
<hr/>
<img src="{{ fotoArt.foto.url}}" alt="{{ fotoArt.nombre }}" height="200" width="200">
<hr/>
<div class="row">
<a class="nav-link btn-style" href = "{% url 'actualizar-fotoArt' fotoArt.pk %}">Actualizar</a>
<a class="nav-link btn-style" href = "{% url 'borrar-fotoArt' fotoArt.pk %}">Borrar</a>
</div>
{% endblock %}
fotoArt_form.html
{% extends 'catalogo/base.html' %}
{% block content %}
<h2>Crear/Actualizar Fotos Artículos</h2>
<form action="" method="post">
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<input type="submit" value="Enviar" />
</form>
{% endblock %}
When introducing new photos (fotoArt_form.html) it throws the error "The attribute 'photo' has no associated file.", although it actually creates the record in the database, but with the photo field empty, consulted from PgAdmin:
And in the consultation of the photo through detail_photoArt.html, it throws me the same error. I haven't entered any url to control the photos because I don't need it, but I've also tried inserting one just in case:
re_path(r'^media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT}),
and in the runserver it already throws this error:
File "E:\Trastero\Trastero\urls.py", line 33, in <module>
re_path(r'^media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT}),
File "C:\Users\Administrador\Envs\gelaDjango22\lib\site-packages\django\urls\conf.py", line 73, in _path
raise TypeError('view must be a callable or a list/tuple in the case of include().')
TypeError: view must be a callable or a list/tuple in the case of include().
What is wrong? I've tried a thousand things, and that they say that Django is a framework to create applications "quickly", hahaha it makes me laugh, surely it refers to the experts. I have also tried with src= "{{ fotoArt.foto.path}}" and with the same error.
You have several errors in your code I list and explain below:
When you work with files in the form it must contain the
enctype='multipart/form-data'
.The folder
media
must go in the root of the project, to be able to be visualized by the different modules of your application (you can see in yoursettings.py
that you located it in theraiz/media/
noteMEDIA_URL = '/media/'
)in
Django
order for the folders to be accessible you must add the static folder tourls.py
; You did all the configuration and you missed this step.