Django: Querying to ImageField all images are being rendered

1.4k views Asked by At

So my problem is that when I try to query to the image url so it can be posted to its corresponding Post all the images that have been uploaded to the media folder is being rendered, even though in the admin panel it shows that each post has it's own image and they are assigned to different posts, instead all of them are being rendered together for each and every post.

The models that I have are SellPost which is for creating a post and SellPostImage is for assigning the image to the post.

models.py

class SellPost(models.Model):
    user = models.ForeignKey(User)
    title = models.CharField(max_length=128)
    category = models.ForeignKey(Category)
    type = models.ForeignKey(SellPostType, default=None)
    body = models.CharField(max_length=400)
    price = models.DecimalField(decimal_places=1, max_digits=5, default=0.0)
    views = models.IntegerField(default=0)
    likes = models.IntegerField(default=0)
    slug = models.SlugField(unique=True, default='automatic')

    def save(self, *args, **kwargs):
        self.slug = slugify(self.title)
        super(SellPost, self).save(*args, **kwargs)

    def __unicode__(self):
        return self.title




class SellPostImage(models.Model):
    user = models.ForeignKey(User, null=True)
    post = models.ForeignKey(SellPost)
    pictures = models.ImageField(upload_to='post_images', blank=True)

    def __str__(self):
        return "{}".format(self.post)

    class Meta:
        verbose_name_plural = "Post Images"

In the view I tried to create a context dict (because I'm a newbie in Django and have learned that from Tango with Django so I went with it) for the post and then the images:

views.py

def post(request, post_name_slug):

    context_dict = {}
    try:
        post = SellPost.objects.get(slug=post_name_slug)
        context_dict['post'] = post

        post_image = SellPostImage.objects.all()
        context_dict['post_image'] = post_image

    except SellPost.DoesNotExist:
        pass

    return render(request, 'p.html', context_dict)

and here is how I tried to render them in the HTML file.

p.html

 <ul>
        {% for post in posts %}
        <li><a href="/p/{{ post.slug }}">{{ post.title }}</a> </li>
        {% for post_images in post_image %}

        <img style="width:200px; height:200px;" src="{{ post_images.pictures.url }}" />

    {% endfor %}
        {% endfor %}
    </ul>
2

There are 2 answers

2
AudioBubble On BEST ANSWER

You'll want to filter the SellPostImage for the retrieved post:

post = SellPost.objects.get(slug=post_name_slug)
context_dict['post'] = post

post_image = SellPostImage.objects.filter(post=post)
context_dict['post_image'] = post_image

But you can just as easily put that logic part directly into your template:

 {% for post in posts %}
    <li><a href="/p/{{ post.slug }}">{{ post.title }}</a> </li>
    {% for post_images in post.sellpostimage_set.all %}
      <img style="width:200px; height:200px;" src="{{ post_images.pictures.url }}" />
    {% endfor %}
{% endfor %}

and then you can remove the SellPostImage in your views:

try:
    post = SellPost.objects.get(slug=post_name_slug)
    context_dict['post'] = post
except SellPost.DoesNotExist:
    pass
4
OrenD On

In your post method you query for all SellPostImages:

post_image = SellPostImage.objects.all()

That's why you get all images for each post.

You can filter only the images associated with a post by doing the following instead:

post_image = SellPostImage.objects.filter(post=post)

It will provide all images for that specific post.