Photo by prateekkatyal Unsplash
Photo by prateekkatyal on Unsplash

Implementing likes in Django

sriram
sriram
June 13

Did you searched the whole web for implementing likes for your social media application, or a blog application or anything? and did not get a clear idea about it? Don't worry in this post I will guide you through creating a better database design for like, working with likes in views.py with better and faster effeciency and creating front end with jQuery. If you like dark mode switch to full screen. Without further delay let's get started πŸ˜ƒπŸ˜‰πŸ˜ƒ .

Database structure : 

Pay attention I repeat pay attention to this part. It's database buddy later on it's not easy to get your hands dirty, So the first time itself we should create best database design possible.  Before showing you the models let me first show my django project structure.

folder structure for simple like project with posts app 
folder structure for simple like project with posts app 

I made this simple for this post but you can go ahead with your app. Don't need to create a separate app. For example if you have blog or social posts or any app you can create likes model in that app itself. I have created this web app you're currently are in this website I have created 2 apps for blog and  shorts ( small blog ) so in both the app's model I have created a Like class. Be sure to like this post by clicking like button on top left πŸ‘†πŸ’•. similarly if you wanna expand your project like me you can have separate likes for separate apps. 

Note : I have researched long time and came up with this database design because this design helps in scalability and faster data fetching. So let's see how to create model for likes.

I have a simple post class with image, title, caption, and author

I have set ImageField with blank and null to true to make this article short so, we don't need to configure media files in settings. post_by is the owner of the post and it's set to foreignkey because one post can have only one user. Next we will have separate class for likes.

Many users can like many image so we have created 2 rows one will contain user id and another will contain the post id. For example

liked_on is not necessary. If you'd like to keep track of user's interest change over time you can keep that. If you hire data scientists later if your project becomes great this data will be of great help. The below image explains it well πŸ˜‚πŸ€£πŸ˜‚.

data scientist loves DATA
data scientist loves DATA
Data scientist looks for huge data
Data scientist looks for huge data

I have another image I cannot put it here DM in instagram  I will send you.

Unique constraint ensures that same user cannot like the same post 2 or many times like below. Know more about constraints here.

And finally __str__ helps us to easily know which user likes which post. Nice idea? is it not? πŸ˜‰πŸ˜‰πŸ˜‰ tell in comment section I love to hear from you guys . Make migration by running python manage.py makemigrations

Outch don't forgot to add your app in installed apps. 

type python manage.py migrate in your terminal and Hit migrate.

Creating views for like button

  1. Get the post id from the client via POST or GET method.
  2. Using the post id get the post object 
  3. Check whether user already liked the post 
  4. if user already liked the post delete the like object. Else add a like object
  5. Finally return success message to client side 

@login_required comes with django decorators . A decorator is a function which takes another function as an argument and returns the original function after performing specific task. It may or may not return the original function based on the code we write in decorator function.  Decorators provide a way to dynamically alter the functionality of your functions. So for example, if you wanted to log information when a function is run, you could use a decorator to add this functionality without modifying the source code of your original function.

In our case login_required takes likes function as an argument and check whether user authenticated or not if authenticated it runs the like function else redirects to settings.LOGIN_URL. in simple words

login_required() does the following:

We have gone away from the topic. Just to make sure that you understand every piece of code πŸ‘©πŸ»β€πŸ’». 

To check whether user already liked or not use get_or_create() which takes 2 arguments user id and post id which we define in models.  Here, with concurrent requests, multiple attempts to create a Like object with the same parameters may be made, So to avoid that condition we have used get_or_create(). Even though we have created unique constraint at the database level this function helps to create a like if it does not exist already. This returns 2 values one is a boolean value (stored in var created) and other is the like object itself (stored in var like_object). created value will be true if the object exists else it's value is false. Using if we delete the like object if it already exists. And the liked or removed like is stored in var liked which is to be sent to frontend.

After all the process data is sent using json response(200) is returned to the client side.

To fetch the posts create a function which returns all the posts. and create a list which contains all the liked posts

I assume that you created templates folder in your project's root folder. add added it's location in settings DIRS lists in TEMPLATES variable like below.

Let's see how to create urls for calling the like and posts.

Creating URLS for like button

To make this post short I have called the function in the root urls itself but in your case you can create a separate urls.py file in the app and include it in the root urls.py file.

So idea here is to call the URL '/post/like/' with post id as a post parameter.

Adding some post

before creating frontend we need to add some posts. So first let's register the model for admin panel.

Create super user running python manage.py createsuperuser

Quickly go ahead and create some posts. By the time support me by buying me a coffee by clicking more icon πŸ‘† and the coin icon or click here.

Finally let's add a like button in frontend

I have created home.html in templates and added simple styles to make it look clean.  Create a for loop using django templates and assign to post variable. 

Getting post data

data code
post pk {{ post.pk }}
post title {{ post.title }}
post caption {{post.caption }}
number of likes {{ post.likes.count }}
whether user liked {% if post in liked_posts %} Liked {% else %} Like {% endif %} 
csrfmiddleware token {% csrf_token %}

Note that likes is the related name used in Like model. Use if statement  to check whether post present in user's liked posts which we created in views.py.

Html πŸ‘‡

Finally we should make a AJAX call to backend to add like or remove like.

Steps to call like function using AJAX

  1. Add jQuery from CDN
  2. create a function which calls the backend URL for like
  3. If response status is 1 there will be 2 options
  4. Post not liked already : increase the like counter and  set innerhtml of button liked. 
  5. Post liked already : decrease the like counter and replace inner html with like.

If the AJAX call is success we will check the liked variable which is sent to frontend from like function as a jsonresponse. if the liked is true we increment the counter by getting counter id using jQuery you can also use pure javascript i.e.., document.getElementById(post_id). innerHTML; why should you go to javascript if king jQuery does the job πŸ‘‘. If there is a error occurred then inform the user currently I just logged in console. You can use this same idea even for a huge projects πŸ˜ƒ.  

Finally thanks for reading this far I hope you enjoyed this post. Like this post. Follow me for more awesome posts on Django. Put your thoughts in the comment section I'd love to hear from you guys. support us by donating by clicking more icon < coin or click here

Finally thanks for reading ✌.


Today's deal from platiplus

More from the author

Photo by prateekkatyal Unsplash

Implementing likes in Django

Comments (0)

Add a Comment

Reply