Sammy
Sammy

Reputation: 321

How to use Django-hitcount package to build a view count

I am learning Django and came across this Django package called 'Django-hitcount'. But I don't know how to use it in my count. I want to display the number of times that an object is viewed

Below is my views.py

def home(request):
    songs = Songs.objects.all()
    return render(request, 'explore/home.html', {'songs': songs})
    count_hit = True

This is my models.py

class Songs(models.Model, HitCountMixin):
    ...
    plays = GenericRelation(HitCount, object_id_field='object_pk', related_query_name='hit_count_generic_relation')
    updated = models.DateTimeField(auto_now=True, auto_now_add=False)

    class Meta:
        ordering = ['-updated']

    def __str__(self):
        return self.song_title

And my html file ...

    <p><strong><h5>{{ song.song_title }}</h5></strong></p>
    <p><h5>{{ song.artist }}</h5></p>
    <span>plays: {% get_hit_count for [song] %}</span>

Upvotes: 1

Views: 3679

Answers (1)

Nico Griffioen
Nico Griffioen

Reputation: 5405

You are mixing up different ways of counting the hits and displaying the hit counts.

First of all, to count the number of hits for one object, you'll need to add a DetailView, which shows one single song. This class is also where you add the count_hit parameter Something like this (views.py):

from hitcount.views import HitCountDetailView

class SongDetailView(HitCountDetailView):
    model = Song        
    count_hit = True    
    template = 'song_detail.html'

    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        context = self.get_context_data(object=self.object)
        return redirect(self.object.song.audio_file.url)

HitCountDetailView is hitcount's built in view that gets a single object and adds up the hitcounts.

Add a template to display a single song (song_detail.html):

<p><strong><h5>{{ object.song_title }}</h5></strong></p>
<p><h5>{{ object.artist }}</h5></p>
<span>plays: {% get_hit_count for [object] %}</span>

Then in your urls add the following pattern (urls.py):

urlpatterns = [
    ...
    path('song/<int:id>/', SongDetailView.as_view(), name='song-detail'),
    ...
]

You now have two urls, one that leads to home, and one that leads to song/, the first should display a list of songs, the second just one song.

There is some unnecessary/wrong code in your original code, which I will explain below:

Your models.py has a generic relation, to HitCount, which is not necessary, unless you want to do some direct lookups to this models HitCount, but for now, you can leave it out.

The HitCountMixin should be added to a view, specifically a class based view, but not to a model. You models.py should look like this:

class Songs(models.Model):
    ...
    updated = models.DateTimeField(auto_now=True, auto_now_add=False)

    class Meta:
        ordering = ['-updated']

    def __str__(self):
        return self.song_title

Your template looks like it's part of a file, but if it's not, it's not correct. Better would be to loop over each song (You can also link to your new detail-view), like this:

{% for song in songs %}
    <p><strong><h5>{{ song.song_title }}</h5></strong></p>
    <p><h5>{{ song.artist }}</h5></p>
    <span>plays: {% get_hit_count for [song] %}</span>
    <a href="{% url 'song-detail' song.id %}">Play song</a>
{% endfor %}

Upvotes: 1

Related Questions