Building a Social Media App Part 13: Adding Images to Posts

LegionScript
3 min readApr 26, 2021

Video Tutorial

Code on Github

In this tutorial, we are going to add more to our social network application. This time we will add the ability to upload a image in a post. We will add a button to select a file and then we will show it above the text of the post. We will need to make some updates to our PostModel to handle this. Let’s first start with fixing a small bug in the social feed.

Fixing a Social Feed Bug

The first thing to do is to fix the issue with our social feed, there is an issue where the posts aren’t being filtered correctly in our post method, all we need to do is update it to match the get method.

social/views.py

logged_in_user = request.userposts = Post.objects.filter(author__profile__followers__in[logged_in_user.id]).order_by(‘-created_on’)

Updating the Post Model

Next we need to update the post model to hold an image path if the post has one, we also want to add blank=True and null=True so that this field can be left empty and blank in the form. Here is the updated PostModel.

social/models.py

class Post(models.Model):  body = models.TextField()  image = models.ImageField(upload_to='uploads/post_photos/',   blank=True, null=True)  created_on = models.DateTimeField(default=timezone.now)  author = models.ForeignKey(User, on_delete=models.CASCADE)  likes = models.ManyToManyField(User, blank=True, related_name='likes')  dislikes = models.ManyToManyField(User, blank=True, related_name='dislikes')

Add the Image Field to the Post Model Form

Now we need to update our form so that it displays a field for the user to select an image to upload. This will just require one extra line added to our current form. We want to make sure to make this field not required as well so that the user isn’t forced to upload an image.

social/forms.py

image = forms.ImageField(required=False)

Updating the PostList View

The next step is to update our view to handle the image being in our form. In our form in the post method we passed in the request.POST already we also want to pass in request.FILES as well.

social/views.py

form = PostForm(request.POST, request.FILES)

Updating the post_list.html and the profile.html Templates

Now we need to update our HTML form and if there is an image add it to the post. We need to change the enctype of our forms that have files otherwise the files won’t be sent with the request.

social/templates/social/post_list.html

<div class="row justify-content-center mt-3 mb-5">  <div class="col-md-5 col-sm-12">    <form method="POST" enctype="multipart/form-data">      {% csrf_token %}      {{ form | crispy }}      <div class="d-grid gap-2">        <button class="btn btn-success mt-3">Submit!</button>      </div>    </form>  </div></div>

social/templates/social/profile.html

<div class="position-relative">  {% if post.image %}  <img src="{{ post.image.url }}" class="post-image" />  {% endif %}  <p>{{ post.body }}</p>  <a class="stretched-link" href="{% url 'post-detail' post.pk %}"></a></div>

Updating the post_edit.html Template

Finally, the last step is to update the enctype on our edit form so that if a post is edited the image changes are saved as well.

social/templates/social/post_edit.html

<form method="POST" enctype="multipart/form-data">  {% csrf_token %}  {{ form | crispy }}  <div class="d-grid gap-2">    <button class="btn btn-success mt-3">Submit!</button>  </div></form>

Adding the CSS Styles

We want to add the styles to make the photo look correctly. We just need to set the size limits and we will round the corners a little as well as add a little margin on the bottom.

static/style.css

.post-image {max-width: 100%;height: auto;border-radius: 10px;margin-bottom: 10px;}

And that should finish up our addition to our application today. This was a little quicker and easier than most, I want to add a harder addition next so I felt it would be better to take care of this first. Next we will add a way to DM other users.

--

--