Django 'model' object is not iterable error - django

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.

Related

don't show images from ImageField in django template

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 %}

raise self.RelatedObjectDoesNotExist( Portal.models.logger.Student.RelatedObjectDoesNotExist: logger has no Student

I keep getting this error everytime I try to access the class assignment page.
Below is the code of my project.
Models.py
class logger(AbstractUser):
is_student = models.BooleanField(default=False)
is_teacher = models.BooleanField(default=False)
class Student(models.Model):
username = models.OneToOneField(logger,on_delete=models.CASCADE,primary_key=True,related_name='Student')
name=models.CharField(max_length=250)
roll_no = models.CharField(max_length=50)
email = models.EmailField(max_length=254)
def __str__(self):
return self.name
class Meta:
ordering = ['roll_no']
class Teacher(models.Model):
username = models.OneToOneField(logger,on_delete=models.CASCADE,primary_key=True,related_name='Teacher')
name = models.CharField(max_length=250)
subject_name = models.CharField(max_length=250)
email = models.EmailField(max_length=254)
class_students = models.ManyToManyField(Student,through="StudentsInClass")
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('teacher_detail',kwargs={'pk':self.pk})
Views.py
#login_required
def class_assignment(request):
student = request.user.Student
assignment = SubmitAssignment.objects.filter(student=student)
assignment_list = [x.submitted_assignment for x in assignment]
return render(request,'class_assignment.html',{'student':student,'assignment_list':assignment_list})
class_assignment.html
{% extends 'base.html' %}
{% block content %}
<div class="container">
<div class="jumbotron">
{% if student.student_assignment.count == 0 %}
<h2>No assignments Yet</h2>
{% else %}
<table class="table">
<thead class="thead-dark">
<tr>
<th scope="col">#</th>
<th scope="col">Assignment Name</th>
<th scope="col">Uploaded By</th>
<th scope="col">Uploaded Date</th>
<th scope="col">Download</th>
<th scope="col">Status</th>
</tr>
</thead>
<tbody>
{% for assignment in student.student_assignment.all %}
<tr>
<th scope="row">{{ forloop.counter }}</th>
<td>{{ assignment.assignment_name }}</td>
<td>{{ assignment.teacher }}</td>
<td>{{ assignment.created_at }}</td>
<td>Download</td>
{% if assignment in assignment_list %}
<td>Submitted</td>
{% else %}
<td>Submit</td>
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
</div>
</div>
{% endblock %}
Can anyone please help me and tell me if something is wrong in the code or not, I have tried almost everything including syncing the database, trying to migrate the project, deleting and re-creating the database.
Any help would be appreciated, Thank you and if you need anything else please comment and I'll upload it.

display number of views for each post for a specific author

i want to print number of views for a specific post for e.g barack obama = 3 albert einstein = 1 elon musk = 0 that's it,
but it print multiple values for each entries as you can see in the image.
so how to achieve this. should i have to use dictionary or what ?
enter image description here
models.py
class ObjectViewed(models.Model):
user = models.ForeignKey(User, blank=True, null=True, on_delete=models.CASCADE)
ip_address = models.CharField(max_length=220, blank=True, null=True)
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) # User, Blog, or any other models
object_id = models.PositiveIntegerField() # User id, Blog id, or any other models id
content_object = GenericForeignKey('content_type', 'object_id')
timestamp = models.DateTimeField(auto_now_add=True)
views.py
class PostListView(ListView):
model = Post
template_name = 'edmin/post/postList.html'
context_object_name = 'posts'
ordering_by = ['-created']
def get_queryset(self):
post=Post.objects.filter(author=self.request.user)
return post
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
post=Post.objects.filter(author=self.request.user)
c_type = ContentType.objects.get_for_model(Post)
context['count_view'] = [ObjectViewed.objects.filter(content_type=c_type, object_id=p.id) for p in post ]
print(context['count_view'])
return context
postList.html
<table id="table_id" class="table display" border='2' align="center">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Title</th>
<th scope="col">Banner Title</th>
<th scope="col">Created</th>
<th scope="col">Number of Views</th>
<th scope="col">Status</th>
<th scope="col">Edit</th>
<th scope="col">Delete</th>
</tr>
</thead>
<tbody style="color:#000">
{% for post in posts %}
{% if post.status == 'Draft' %}
{% else %}
<tr>
<th scope="row">{{ forloop.counter }}</th>
<td><a style="color:blue" href="{% url 'edmin:post_detail_view' pk=post.pk %}">{{ post.title }}</a></td>
<td>{{ post.banner_title }}</td>
<td>{{ post.created }}</td>
<td>
{% for c in count_view %}
{{ c|length }}
{% endfor %}
</td>
<td>{{ post.status }}</td>
<td>Edit</td>
<td>Delete</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
This is the problem of your code:
<td>
{% for c in count_view %}
{{ c|length }}
{% endfor %}
</td>
I believe count_view is the list of all the view count across objects? If that's the case, the event in your screen will happen because you displayed all items in the count_view list. You might need to change this part to:
<td>
{{ count_view.forloop.counter }}
</td>
You need to get the view for a specific post, not to print out every single one of them. You might need to check as I don't know where your list starts, but this is briefly how this works.
Research

Displaying data from intermediate table in a many-to-many relation

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),

Grouping models in template

I have two related models:
class Package(models.Model):
package_name = models.CharField(max_length=64)
ptype = models.CharField(max_length=16)
class Extra(models.Model):
package = models.ForeignKey(Package, related_name='package')
data = models.DecimalField(max_digits=8, decimal_places=2, blank=True, null=True)
information = models.CharField(max_length=1024, blank=True)
view.py:
def show_package(request):
list = get_list_or_404(Package, ptype='sometype')
return render(request, 'table.html', {'list': list})
and template:
{% for row in list %}
<table class="provider_list">
<tr>
<td>{{ row.package_name}}</td>
<td>{{ row.ptype }}</td>
</tr>
</table>
{% endfor %}
How can I add an additional table (from Extra model) next to the prelated table?
Like:
<table>
{% for extra_row in extra_list %}
<tr>
<td>{{ extra_row.data }}</td>
<td>{{ extra_row.information }}</td>
</tr>
{% endfor %}
</table>
Thanks.
try this:
{% for package in list %}
<table class="provider_list">
<tr>
<td>{{ package.package_name}}</td>
<td>{{ package.ptype }}</td>
<td>
<!-- fetch the related data -->
<table>
{% for extra in package.extra_set.all %}
<tr>
<td>{{ extra.data }}</td>
<td>{{ extra.information }}</td>
</tr>
{% endfor %}
</table>
</td>
</tr>
</table>
{% endfor %}
You show modify your Extra related_name on package ForeignKey.
models.py
class Extra(models.Model):
extra = models.ForeignKey(Package,related_name='extra_related_name') #default for related_name would be 'extra_set'
You can access all extra fields via:
extras = list.extra_related_name.all()
Let's imagine you have only one extra existing on every Package model
views.py
def show_package(request):
list = get_list_or_404(Package, ptype='sometype')
list.extra = list.extra_related_name.all()[0]
return render(request, 'table.html', {'list': list})
template
{% for row in list %}
<table class="provider_list">
<tr>
<td>{{ row.package_name}}</td>
<td>{{ row.ptype }}</td>
<td>{{ row.extra.data }}</td>
<td>{{ row.extra.information }}</td>
</tr>
</table>
{% endfor %}
If you are sure that there is at most one extra per package you should look at OneToOneField for easier access. If you are unsure, stick to ForeignKey and add checks in the view to check that you are accessing valid data.