''Uploads' object is not iterable in Django

I am trying to have each model object have it's own page with all the other model objects attached to it, using the modal id, I tried using the {{ img.queryset.all.id }} html tag to display the photo, but that didn't work. I know the problem is in either the views.py or single_page.html, and maybe the models.py but I believe that is unlikely the problem. When I click onto the photo it bring it to a page with the photo icon, it doesn't display it because the photo is unknown. While every time I use {% for x in img %} it says 'Uploads' object is not integrable. If anyone could help that would be great.

modals.py


class Profile(models.Model):
    user = models.OneToOneField(User, on_delete = models.CASCADE, null = False, blank = True)
    first_name = models.CharField(max_length = 50, null = True, blank = True)
    last_name = models.CharField(max_length = 50, null = True, blank = True)
    phone = models.CharField(max_length = 50, null = True, blank = True)
    email = models.EmailField(max_length = 50, null = True, blank = True)
    bio = models.TextField(max_length = 300, null = True, blank = True)
    profile_picture = models.ImageField(default = 'default.png', upload_to = "img/%y", null = True, blank = True)

    def __str__(self):
        return f'{self.user.username} Profile'



class Uploads(models.Model):
    title = models.CharField(max_length = 500, null = True,)
    artiste = models.CharField(max_length=500, null = True,)
    album = models.ForeignKey('Album', on_delete=models.SET_NULL,null=True,blank=True)
    time_length=models.DecimalField(max_digits=20, decimal_places=2,blank=True, null = True,)
    audio_file=models.FileField(upload_to='musics/',validators=[validate_is_audio], null = True,)

    caption = models.CharField(max_length = 100, blank=True)
    file = models.ImageField(upload_to = "img/%y", null = True)
    profile = models.ForeignKey(Profile, on_delete = models.CASCADE, default = None, null = True)
    id = models.AutoField(primary_key = True, null = False)


    def __str__(self):
        return str(self.file) and f"{self.id}"

class Album(models.Model):
    name=models.CharField(max_length=400)

views.py

def profile(request, user):
    img = Uploads.objects.filter(profile_id = request.user.profile)         #Make sure only your account *images stays on the page
    profile = Profile.objects.filter(user = request.user)
    context = {"profile": profile, "img": img}

    return render(request, "main/profile.html", context)

def single_page(request, id):
    img = Uploads.objects.filter(id = id).first()    
    profile = Uploads.objects.filter(id = request.user.id)

    context = { "img": img, "profile": profile}

    return render(request, "main/single_page.html", context)

single_page.html

{% block content %}
<body>

    {% for x in img %}
    <p>{{title}}</p>

    <img src="{{x.file.url}}" height="100%" width="100%"  class="myImg">
    {% endfor %}


</body>
{% endblock %}



Solution 1:[1]

If img is an object, you cannot iterate over it, so for loop is not valid idea. You should be able to access it's url with: {{ img.file.url }}.

Don't use id as variable, it's builtin function. Don't filter Uploads.id by request.user.id because it's not going to work. It's different model.

For single photo you should do in views:

from django.shortcuts import get_object_or_404

def single_page(request, img_id):
    img = get_object_or_404(Uploads, id=img_id)

    context = {"img": img}

    return render(request, "main/single_page.html", context)

single_page.html:

{% block content %}
<body>

    <p>{{ img.title }}</p>

    <img src="{{ img.file.url }}" height="100%" width="100%"  class="myImg">

</body>
{% endblock %}

If you have more pictures of one User, you can find them with:

images = Uploads.objects.filter(profile=self.request.user.profile)
context = {"images": images}

And in template:

{% for img in images %}

    <p>{{ img.title }}</p>

    <img src="{{ img.file.url }}" height="100%" width="100%" class="myImg">

{% endfor %}

And if you want to get profile, don't search it with filter, because you will get QuerySet, not an object instance. To get single object you should do as I've showed you before:

profile = get_object_or_404(Profile, user=request.user)
# or
profile = Profile.objects.get(user=request.user)

or if you really, really prefer filter method:

profile = Profile.objects.filter(user=request.user).first()

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1