Ryan Oh
Ryan Oh

Reputation: 647

How do I count hits of each element in a list in Django?

So I have a page where multiple articles are listed. (To be precise, TITLES that are outlinked to the articles written on Notion template.) And I want to have a filed in my model that counts the number of clicks of each article. (I don't want to use django-hitcount library).
Let me first show you my code.
models.py

class Article(models.Model):
    number = models.IntegerField(primary_key=True)
    title = models.CharField(max_length=20, default="")
    url = models.URLField(max_length=100, default="")
    hits = models.IntegerField(default=0)

template

...
<div class="col text-center">
    {% for q in allArticles %}
        <a href="{{q.url}}"><h2 id={{q.number}}>{{q.title}}</h2></a>
    {% endfor %}
</div>
...

I was thinking of using onclick() event in JavaScript, but then passing data from JavaScript to Django seemed too challenging to me at the moment.
I'd very much appreciate your help. Thanks.

Upvotes: 0

Views: 342

Answers (3)

sigmal
sigmal

Reputation: 66

Well, when you dont take up new challenges you stop learning !

The onclick method looks like the best imo, lets see what others suggest.

honestly, using JS and AJAX to communicate with your django server might be dauting at first but it is quite easy really.

if you know how to create a function in your views.py and know a bit of JS, it's just like any other classic functionnality.

Set up your urls.py for the view function that will add a click to the counter:

path('ajax/add_click', views.add_click name="add_click"),

Then, create your view function (pseudo code):

def add_click(request):
    # retrieve the article
    article_id = request.GET.get("articleId", None)
    # then retrieve the object in database, add 1 to the counter save and return a response

Now the "complicated" part, the ajax request:

function add_one_click(articleId) {
        $.ajax({
            type: "GET",
            url: '/ajax/add_click', // you also can use {% url "app_name:add_click" %}
            data: {
                'articleId': articleId,
            },
            success: function() {
                console.log("hit added to article");
            }
        });
    }

You need to add JS and Ajax lib to your html template for it to works.

Also you need to pass in the onclick attribute the name of the function + the id of the article onclick="add_one_click({{article.id}})"

One more thing, this type of view, if not protected can lead to get false results.

Upvotes: 2

mursalin
mursalin

Reputation: 1181

Edit:

Create a new url that would handle your article click, lets say-

path('article/clicked/<article_number>', views.click_handler, name='click_counter')

Now, in your template use this url for all the article

<div class="col text-center">
    {% for q in allArticles %}
        <a href="{% url 'app_name:click_counter' q.number %}"><h2 id={{q.number}}>{{q.title}}</h2></a>
    {% endfor %}
</div>

and in your views.py create a new controller

def click_handler(request, article_number):
    article = Article.objects.get(number=article_number)
    article.hits += 1
    article.save()
    # now redirect user to the outer link
    return redirect(article.url)

Upvotes: 0

jaswanth
jaswanth

Reputation: 525

Instead of having q.url have a new URL(/article_count?id=q.id) which you will define on your Django project

def article_count(req):
    _id = req.GET.get('id', '')
    # Query Aritcle and get object
    q = Article.objects.get(id=_id)
    # update the fields for clicks
    q.hits += 1
    q.save()
    # redirect the page
    return redirect(q.url)

Upvotes: 0

Related Questions