четверг, 14 апреля 2016 г.

Счетчик кликов по ссылке в Django

Появилась задача для подсчета числа переходов на Django сайте.

Для этого создадим промежуточную страницу /go/<thing_id>/:



Обработчик страницы будет производить две простых вещи:
 - увеличение счетчика числа переходов;
 - перенаправление пользователя на нужный урл;

1. Для начала напишем простенький тест:

       
class ThingCounterTest(unittest.TestCase): 

    def setUp(self):

        self.thing _ = Thing.objects.get_or_create(name="test_channel")



    def tearDown(self):

        self.thing.delete()



    def test_thing_counters(self):

        self.thing.add_click()

        self.assertEqual(self.thing.clicks_today, 1)

        self.assertEqual(self.thing.clicks_yesterday, 0)

        self.assertEqual(self.thing.clicks_last_week, 1)

        self.assertEqual(self.thing.clicks_last_month, 1)

       
 


2. Добавим таблицу в БД для подсчета кликов:



       

class ThingClick(models.Model):

    thing  = models.ForeignKey(

        Thing, related_name='clicks',

        on_delete=models.CASCADE)

    clicked_at = models.DateTimeField(auto_now_add=True)



    class Meta:

        verbose_name = u"Клик на товар"

        verbose_name_plural = u"Клики на товары"



       
 

Не забываем сделать миграцию.

3. Добавим функции для подсчета кликов за последние периоды:

         (models.py)

class Thing(models.Model):

    ...



    def add_click(self):

        self.clicks.create()



    @property

    def clicks_today(self):

        yesterday = timezone.now().date() - timedelta(days=1)

        return self.clicks.filter(

            clicked_at__gt=yesterday).count()



    @property

    def clicks_yesterday(self):

        yesterday = timezone.now().date() - timedelta(days=1)

        return self.clicks.filter(

            clicked_at__gte=yesterday,

            clicked_at__lt=timezone.now().date()).count()



    @property

    def clicks_last_week(self):

        week_ago = timezone.now().date() - timedelta(days=7)

        return self.clicks.filter(clicked_at__gte=week_ago).count()



    @property

    def clicks_last_month(self):

        month_ago = timezone.now().date() - timedelta(days=30)

        return self.clicks.filter(clicked_at__gte=month_ago).count()

       
 



4. напишем вид, который будет считать ссылки и редиректить на нужную страницу (ссылка на которую у меня уже хранится в thing.link):
 (views.py)
        
def thing_click_admitad(request, thing_id=None):

    """

        Переход по ссылке thing.link со счетчиком кликов

        по каналу

    """

    if thing_id:

        thing = get_object_or_404(

            Thing.objects.select_related("thing_set__channel"),

            id=thing_id)

        try:

            thing.add_click()

        except Exception, e:

            logger.error("Failed to add a click for thing: " + str(e))

        if thing.link:

            return HttpResponseRedirect(thing.link)

        else:

            raise Http404


5. Добавим в urls.py соответствующий шаблон ссылок:


       

    url(r"^go/(?P<thing_id>[0-9]+)/$",
        "statistic.views.thing_click",
        name="counted_link"),



6. Наконец, добавим в админку отображение результатов нашей статистики:


       
class ThingAdmin(admin.ModelAdmin):
    list_display = (
        "name", "url", "clicks_today", "clicks_yesterday",
        "clicks_last_week", "clicks_last_month")

    def clicks_today(self, obj):
        return obj.clicks_today
    clicks_today.short_description = u'Кликов сегодня'

    def clicks_yesterday(self, obj):
        return obj.clicks_yesterday
    clicks_yesterday.short_description = u'Кликов вчера'

    def clicks_last_week(self, obj):
        return obj.clicks_last_week
    clicks_last_week.short_description = u'Кликов за последнюю неделю'

    def clicks_last_month(self, obj):
        return obj.clicks_last_month
    clicks_last_month.short_description = u'Кликов за последний месяц' 

 

Комментариев нет:

Отправить комментарий