Htmx

HTMX adding Likes With No Refresh

brian | Published: Feb. 25, 2024, 2:19 p.m. | Updated: May 25, 2025, 5:58 p.m.

Profile Picture

Have a section for the likes (Main article page)



<form>
{% csrf_token %}
    <div class="like-section">
          <ion-icon class="view-home" name="eye-sharp"> </ion-icon>  <h1 class="like-count"  >{{ 
          article.views }}  </h1>

    {% include 'code-snippets/like-page.html' %}
        <!-- the include is the block of code were replacing-->        
               
    </div>
</form>

 

Create the likes section in another HTML file, I recomend creating a seperate folder called snippets, and put the HTML file inside there

<div class="main" id="main">

    {% if user.is_authenticated %}
        {% if profile in article.likes.all %}
            
            <a class="cursor-pointer" style=" text-decoration: none; color: inherit;" hx-post="{% url 'like-article-page' slug=article.slug pk=article.pk %}"  hx-target="#main" hx-swap="outerHTML"  > <ion-icon id="like-home" class="like-home" name="heart-sharp"></ion-icon> <h1 class="like-count" id="like-count" > {{ article.likes.count }}</h1> </a> 
        {% else %}
            <a class="cursor-pointer" style=" text-decoration: none; color: inherit;" hx-post="{% url 'like-article-page' slug=article.slug pk=article.pk %}"  hx-target="#main" hx-swap="outerHTML"  > <ion-icon id="like-outline-home" class="like-home" name="heart-outline"></ion-icon> <h1 class="like-count" id="like-count" > {{ article.likes.count }}</h1> </a> 


        {% endif %}


    {% else  %}
        <a  class="cursor-pointer" href="{% url 'home-page'  %}#form-container" style=" text-decoration: none; color: inherit;" > <ion-icon  class="like-home" name="heart-outline"></ion-icon> </a> <h1 class="like-count" id="like-count" > {{ article.likes.count }}</h1> 

    {% endif %}

</div>

 

      Note: you have to pass in all of the context to this file via the view function. In my case i passed in the article and profile

 

  1. Create a div, and then put all the html and logic inside, including the parts where if the user has already liked then have the heart be filled, and if it is not liked have the heart be outlined.
  2.  the target is the div we are going to be changing
  3. the swap is what we are going to be replacing it with
  4. outerHTML the entire target element, along with its contents, is replaced by the fetched content from the server, and this is what we are doing. and just to know innerHTML the entire target element, along with its contents, is replaced by the fetched content from the server.

 

implement the view & logic for when the user clicks the like button

@login_required
def likeArticle(request, slug, pk):
    article = get_object_or_404(Article, slug=slug, pk=pk)
    profile = request.user.profile 

        
    if profile not in article.likes.all():
        article.likes.add(profile)
    else:
        article.likes.remove(profile)
    article.save()
    

    context={
        'article':article,
        'profile':profile,
    }
        

   
    return render(request, 'code-snippets/like-page.html', context)

 

 

Before liking

 

After After liking