Django doesn't show images from ImageField in a template.
models.py
class Employee(models.Model):
emp_name = models.CharField(max_length=200)
emp_email = models.EmailField()
emp_contact = models.CharField(max_length=20)
emp_role = models.CharField(max_length=200)
emp_salary = models.IntegerField()
venue_image = models.ImageField(null=True, blank=True, upload_to="images/")
id = models.UUIDField(default=uuid.uuid4, unique=True, primary_key=True, editable=False)
def __str__(self):
return self.emp_name
template:
<tbody>
{% for emp in employees %}
<tr>
<th scope="row">{{ emp.emp_name }}</th>
<td>{{ emp.emp_email }}</td>
<td>{{ emp.emp_contact }}</td>
<td>{{ emp.emp_role }}</td>
<td>{{ emp.emp_salary}}</td>
<td>
<a style="margin-right: 30px;" href="{% url 'edit-employee' emp.id %}">EDITAR</a>
ELIMINAR
</td>
<td>
{%if venue.venue_image%}
{{venue.venue_image.url}}
{%endif%}
</td>
</tr>
{% endfor %}
</tbody>
views.py
I'm expecting the image here:
The issue is with your if condition in your template. You are getting your employees data with for loop and using variable emp not venue. Use this if condition and your image url will be displayed
{% if emp.venue_image %}
{{emp.venue_image.url}}
{% endif %}
If you want to display the image you need to use image tag like this
{% if emp.venue_image %}
<img src="{{emp.venue_image.url}}">
{% endif %}
Related
I have created a model to have details of job vacancy. The job model has the following fields:
class Job(models.Model):
job_position = models.ForeignKey(Position, on_delete=models.PROTECT, related_name='job_position')
applicants_to_hire = models.IntegerField(null=True, blank=True,
validators=[MinValueValidator(1), MaxValueValidator(15)], default=1)
hiring_team = models.ManyToManyField(Employee, related_name='hiring_team')
class JobListView(LoginRequiredMixin, ListView):
model = Job
template_name = 'recruitment/job_list.html'
context_object_name = 'job_list'
I want to use the hiring_team in a template to show image of each employee (circle avatar), and those images come from the employee model:
class Employee(models.Model):
image = models.ImageField(blank=True, default='blank_profile_picture.jpg')
I've managed to display all images, but they are not in the same table cell, and they add additional table columns:
<tbody>
{% for job in job_list %}
<tr>
<td><span class="employee-table-name">{{ job.job_position }}</span></td>
<td>{{ job.applicants_to_hire }}</td>
{% for team in job.hiring_team.all %}
{% if team.image %}
<td><img src="{{ team.image.url }}" class="rounded-circle img-fluid-80" alt="{{ team }}"></td>
{% endif %}
{% endfor %}
<td>{{ job.job_priority }}</td>
<td>{{ job.job_status }}</td>
<td>{{ job.created|date:"M d, Y" }}</td>
</tr>
{% endfor %}
</tbody>
How can I "concatenate" them to display something like the screenshot below:
This should mean the images should all be under one td block, so just put the td outside of the loop:
<td>
{% for team in job.hiring_team.all %}
{% if team.image %}
<img src="{{ team.image.url }}" class="rounded-circle img-fluid-80" alt="{{ team }}">
{% endif %}
{% endfor %}
<td>
I have a problem that I would like you to help me.
I have a list of users that shows fine, but when I try to edit a user I get the error: Django 'Residente' object is not iterable. This is my code:
residente_list.html
<div class="card-body">
{% if not obj %}
<div class="alert alert-info">No hay Residentes</div>
{% else %}
<table class="table table-striped table-hover">
<thead>
<th>Nombres</th>
<th>Genero</th>
<th>T.Documento</th>
<th>N.Documento</th>
<th>Residencia</th>
<th>Estado</th>
<th class="all">Acciones</th>
</thead>
<tbody>
{% for item in obj %}
<tr>
<td>{{ item.nombre_completo }}</td>
<td>{{ item.genero }}</td>
<td>{{ item.t_doc }}</td>
<td>{{ item.numero_doc }}</td>
<td>{{ item.residencia }}</td>
<td>{{ item.estado|yesno:"Activo, Inactivo" }}</td>
<td>
<i class="far fa-edit"></i>
<i class="far fa-trash-alt"></i>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
</div>
views.py
class ResidenteEdit(LoginRequiredMixin, generic.UpdateView):
model = Residente
template_name = "res/residente_form.html"
context_object_name = "obj"
form_class = ResidenteForm
success_url = reverse_lazy("res:residentes_list")
login_url = 'bases:login'
success_message = "Residente Editado Satisfactoriamente"
urls.py
path('residentes/edit/<int:pk>', ResidenteEdit.as_view(), name='residentes_edit'),
models.py
class Residente(models.Model):
nombre_completo = models.CharField(
max_length=100,
unique=True)
genero = models.ForeignKey(Genero, on_delete=models.CASCADE)
t_doc = models.ForeignKey(Tdocs, on_delete=models.CASCADE)
numero_doc = models.CharField(max_length=100)
residencia = models.ForeignKey(Predio, on_delete=models.CASCADE)
estado = models.BooleanField(default=True)
Thanks for help
When you are in a list view you are usually dealing with a lot of objects (in your case, a lot of Residente's), but when you are editing them you only have one, therefore, you dont need the
{% for item in obj %}
You can do just
obj.nombre_completo
obj.genero
#...
#etc
This should be done in your residente_form.html file.
I have the suspicion you are trying to run a loop in your residente_form.html. If you still can't solve your problem, try posting your residente_form.html here.
I'm working on a project on django, I'm using the built in view ArchiveListView, and I want to sort records to be grouped by a common attribute.
So django ORM don't have a group by query, so I tried to do this on the template using regroup tag, but I think it take a long time and it doesn't give me the grouped record as I want
this is the models I have :
class Vehicle(models.Model):
serie = models.CharField(max_length=18, unique=True, blank=True, null=True)
matricule = models.CharField(max_length=18, unique=True, blank=True, null=True)
ww = models.CharField(max_length=18,blank=True, null=True)
marque_id = models.ForeignKey('Marque', blank=True, null=True, on_delete=models.SET_NULL)
entry_into_service = models.DateField(auto_now=False, auto_now_add=False, blank=True, null=True)
mouchard = models.DateField(auto_now=False, auto_now_add=False, blank=True, null=True)
extinguisher = models.DateField(auto_now=False, auto_now_add=False, blank=True, null=True, help_text="extincteur expiratiOn date")
city_id = models.ForeignKey('City', blank=True, null=True, on_delete=models.SET_NULL)
region_id = models.ForeignKey('Region', blank=True, null=True, on_delete=models.SET_NULL)
driver_id = models.ForeignKey('Driver', blank=True, null=True, on_delete=models.SET_NULL)
class Meta:
ordering = ['serie','matricule']
def __str__(self):
return (self.matricule)
class GazStation(models.Model):
name = models.CharField(max_length=128, blank=True)
city_id = models.ForeignKey('City', blank=True, null=True, on_delete=models.SET_NULL)
geo_localization = gis_models.PointField(blank=True, null=True)
class Meta:
ordering = ['city_id','name']
def __str__(self):
return '%s %s' % (self.name, self.city_id.city)
class Refuel(models.Model):
vehicle_id = models.ForeignKey('Vehicle', blank=True, null=True, on_delete=models.SET_NULL)
driver_id = models.ForeignKey('Driver', blank=True, null=True, on_delete=models.SET_NULL, limit_choices_to ={'is_driver':True})
Controlor_id = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True, related_name='controlor_refuel', on_delete=models.SET_NULL, limit_choices_to ={'is_controlor':True})
gaz_station_id = models.ForeignKey('GazStation', blank=True, null=True, on_delete=models.SET_NULL)
date_time_creation = models.DateTimeField(auto_now=False, auto_now_add=True)
date_time_modified = models.DateTimeField(auto_now=True, blank=True)
odometer_reading = models.PositiveIntegerField(blank=True)
fuel_quantity = models.DecimalField(max_digits=5, decimal_places=2)
fuel_unit_price = models.DecimalField(max_digits=6, decimal_places=2)
class Meta:
ordering = ['gaz_station_id','-date_time_creation']
def __str__(self):
return (self.vehicle_id.serie)
and this is the class view I'm using:
####### refuel view filtred by year #################
class RefuelsListViewSup(LoginRequiredMixin, YearArchiveView):
queryset = Refuel.objects.order_by('vehicle_id').all()
date_field = "date_time_creation"
make_object_list = True
allow_future = True
and the template to display this view is:
{% extends 'base.html' %}
{% load mathfilters %}
{% block title %}
<title>Refuels Archive</title>
{% endblock title %}
{% block content %}
<div class="container">
<h1>La liste des gazoile archivé </h1>
<ul>
{% for date in date_list %}
<li>{{ date|date }}</li>
{% endfor %}
</ul>
<div>
<h1>All Refuels for {{ year|date:"Y" }}</h1>
{% regroup object_list by vehicle_id as vehicle_refuel %}
<ul>
{% for vehicle_id in vehicle_refuel %}
<p>
<li>Les pleints fait pour {{ vehicle_id.grouper}} sont:</li>
</p>
<table border="2">
<thead class="table-dark">
<th colspan="2">Driver name :</th>
<th>Driver number :</th>
<th>Gaz Station : </th>
<th>Date :</th>
<th>Kilometrage :</th>
<th>Quantity of Fuel: </th>
<th>Litre Price (Dh): </th>
<th>Totale (Dh)</th>
<th>City</th>
</thead>
<tbody id="body-table"><tr>
{% for refuel in vehicle_id.list %}
<tr>
<td colspan="2">{{ refuel.driver_id.first_name}} {{ refuel.driver_id.last_name }}</td>
<td>{{ refuel.driver_id.registration_number }}</td>
<td>{{ refuel.gaz_station_id.name}}</td>
<td>{{ refuel.date_time_creation }}</td>
<td>{{ refuel.odometer_reading }}</td>
<td>{{ refuel.fuel_quantity }}</td>
<td>{{ refuel.fuel_unit_price }}</td>
<td>{{ refuel.fuel_quantity|mul:refuel.fuel_unit_price }}</td>
<td>{{ refuel.gaz_station_id.city_id.city }}</td>
</tr>
{% endfor %}
</tbody>
{% endfor %}
</ul>
</div>
</div>
{% endblock content %}
You have two errors in your html
random <tr> element with no closing tag.
<tbody id="body-table"><tr>
{% for refuel in vehicle_id.list %}
no closing tag for <table>
</tr>
{% endfor %}
</tbody>
<!-- missing </table> here-->
{% endfor %}
</ul>
Because I can't run your code I have assumed that the <tr> tag is not supposed to be there.
Therefore, hopefully this fixes your problem.
{% extends 'base.html' %}
{% load mathfilters %}
{% block title %}
<title>Refuels Archive</title>
{% endblock title %}
{% block content %}
<div class="container">
<h1>La liste des gazoile archivé </h1>
<ul>
{% for date in date_list %}
<li>{{ date|date }}</li>
{% endfor %}
</ul>
<div>
<h1>All Refuels for {{ year|date:"Y" }}</h1>
{% regroup object_list by vehicle_id as vehicle_refuel %}
<ul>
{% for vehicle_id in vehicle_refuel %}
<p>
<li>Les pleints fait pour {{ vehicle_id.grouper}} sont:</li>
</p>
<table border="2">
<thead class="table-dark">
<th colspan="2">Driver name :</th>
<th>Driver number :</th>
<th>Gaz Station : </th>
<th>Date :</th>
<th>Kilometrage :</th>
<th>Quantity of Fuel: </th>
<th>Litre Price (Dh): </th>
<th>Totale (Dh)</th>
<th>City</th>
</thead>
<tbody id="body-table">
{% for refuel in vehicle_id.list %}
<tr>
<td colspan="2">{{ refuel.driver_id.first_name}} {{ refuel.driver_id.last_name }}</td>
<td>{{ refuel.driver_id.registration_number }}</td>
<td>{{ refuel.gaz_station_id.name}}</td>
<td>{{ refuel.date_time_creation }}</td>
<td>{{ refuel.odometer_reading }}</td>
<td>{{ refuel.fuel_quantity }}</td>
<td>{{ refuel.fuel_unit_price }}</td>
<td>{{ refuel.fuel_quantity|mul:refuel.fuel_unit_price }}</td>
<td>{{ refuel.gaz_station_id.city_id.city }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endfor %}
</ul>
</div>
</div>
{% endblock content %}
I have 3 models that follow the principle described in Django documentation (https://docs.djangoproject.com/en/2.2/topics/db/models/#extra-fields-on-many-to-many-relationships):
class Topic(models.Model):
key = models.CharField(max_length=255, primary_key=True)
persons = models.ManyToManyField('Person', through='Interest')
class Person(models.Model):
first_name = models.CharField(max_length=255)
last_name = models.CharField(max_length=255)
interests = models.ManyToManyField('Topic', through='Interest')
class Interest(models.Model):
person = models.ForeignKey(Person, on_delete=models.CASCADE)
topic = models.ForeignKey(Topic, on_delete=models.CASCADE)
source = models.ForeignKey(TopicSource, on_delete=models.CASCADE)
The views.pyis really simple:
class TopicsView(generic.ListView):
template_name = 'app/topics.html'
context_object_name = 'topics_list'
def get_queryset(self):
return Topic.objects.all()
The template is actually giving me headaches:
<table>
<tbody class="list">
{% for item in topics_list %}
<tr>
<td>{{ item.key }}</td>
<td>{{ item.person_set.all.count }}</td>
<td>
<ul>
{% for person in item.person_set.all %}
<li>{{ person.last_name }}, {{ person.first_name }} [{% person.interests_set.get(cluster=item) %}]</li>{% endfor %}
</ul>
</td>
</tr>
{% endfor %}
</tbody>
</table>
With {% person.interests_set.get(topic=item) %}, I'm trying to access data from the intermediate table.
How can I display the source of the interest next to the name of the person?
This solution is giving hint on how to do this from the shell but I cannot figure out how to achieve that in the template.
Django templates don't support what you're trying to do out of the box. You would have to create a custom tag to implement what you're trying.
However you could do:
class TopicsView(generic.ListView):
template_name = 'app/topics.html'
context_object_name = 'topics_list'
queryset = Topic.objects.prefetch_related(
Prefetch(
'interest_set',
Interest.objects.select_related('person')
)
Then adjust your template to iterate over the interests.
<table>
<tbody class="list">
{% for item in topics_list %}
<tr>
<td>{{ item.key }}</td>
<td>{{ item.interest_set.all.count }}</td>
<td>
<ul>
{% for interest in item.interest_set.all %}
<li>{{ interest.person.last_name }}, {{ interest.person.first_name }} [ {{ interest.source }} ]</li>{% endfor %}
</ul>
</td>
</tr>
{% endfor %}
</tbody>
</table>
As an alternative to the solution proposed by #schillingt (the accepted solution), I came up with the below solution:
views.py:
class InterestsView(generic.ListView):
template_name = 'app/interests.html'
context_object_name = 'interests_list'
def get_queryset(self):
return Interest.objects.order_by('topic', 'person').all()
template:
{% regroup interests_list by topic as l1%}
<table>
<tbody>
{% for topic in l1 %}
<tr>
<td>{{ topic.grouper }}</td>
<td>{{ topic.list|length }}</td>
<td>
<ul>
{% for item in topic.list%}
<li>{{ item.person.last_name }}, {{ item.person.first_name }} [{{ item.source }}]</li>
{% endfor %}
</ul>
</td>
</tr>
{% endfor %}
</tbody>
</table>
However, the solution from #schillingt is better since it's performance are a lot better (by a factor 2),
I got a model that uses a foreignkey in a manytomany field:
class DefinitionTag(models.Model):
tag = models.CharField(max_length=50, default="Tag")
def __str__(self):
return self.tag
class Definition(models.Model):
name = models.CharField(max_length=100)
definition = models.CharField(max_length=1000)
fundstellen = models.CharField(max_length=300, blank=True)
wissenswertes = models.CharField(max_length=1000, blank=True)
tags = models.ManyToManyField(DefinitionTag)
def __str__(self):
return self.name
this works, and in the admin everything is set up so i can use it. The problem is if i try to display a table with the database entries in my view with the code:
def home(request):
query_results = Definition.objects.all()
context = {
"query_results": query_results
}
return render(request, 'home.html', context)
and in html:
{% for item in query_results %}
<tr>
<td>{{ item.name }}</td>
<td>{{ item.definition }}</td>
<td>{{ item.fundstellen }}</td>
<td>{{ item.wissenswertes }}</td>
<td>{{ item.tags }}</td>
</tr>
{% endfor %}
In the tag column it gives me only:
DefinitionTag.None
How can i display there all the tags choosen in the manytomany field?
I hope i'll get a hint!
Thanks
You need to loop on the m2m field to get all tags. Just referring to it won't give you individual tags that link to it:
{% for item in query_results %}
<tr>
<td>{{ item.name }}</td>
<td>{{ item.definition }}</td>
<td>{{ item.fundstellen }}</td>
<td>{{ item.wissenswertes }}</td>
<td>
{% for tag in item.tags.all %}
{{ tag }}
{% endfor %}
</td>
</tr>
{% endfor %}
If you are not sure how to get all items from m2m field, check out django doc.
Try looping through the tag:
{% for tag in item.tags.all %}
{{ tag }}
{% endfor %}