I am planning to create a page within a blog website where it arranges and displays the all blog posts based on page view count. Not sure how to pull it off.
models.py
class BlogPost(Page):
date = models.DateField(verbose_name="Post date")
categories = ParentalManyToManyField("blog.BlogCategory", blank=True)
tags = ClusterTaggableManager(through="blog.BlogPageTag", blank=True)
body = RichTextField(blank=False)
main_image = models.ForeignKey(
'wagtailimages.Image',
null=True,
blank=False,
on_delete=models.SET_NULL,
related_name='+')
def get_context(self, request, *args, **kwargs):
context = super().get_context(request, *args, **kwargs)
blogposts = self.get_siblings().live().public().order_by('-first_published_at')
context['blogposts'] = blogposts
return context
content_panels = Page.content_panels + [
FieldPanel('date'),
FieldPanel('categories', widget=forms.CheckboxSelectMultiple),
FieldPanel('tags'),
ImageChooserPanel('main_image'),
FieldPanel('body', classname="full"),
]
If you wanted to count views in a slightly more featured way you could use the django-hitcount package.
Your wagtail_hooks.py file would then become:
from hitcount.models import HitCount
from hitcount.views import HitCountMixin
from wagtail.core import hooks
from home.models import BlogPage
@hooks.register("before_serve_page")
def increment_view_count(page, request, serve_args, serve_kwargs):
if page.specific_class == BlogPage:
hit_count = HitCount.objects.get_for_object(page)
hit_count_response = HitCountMixin.hit_count(request, hit_count)
You need to add HitCountMixin to your Page definition, i.e.
from hitcount.models import HitCountMixin
class BlogPage(Page, HitCountMixin):
This allows you to count hits but avoid duplication from the same IP, to reset hits with a management command, and to set the 'active' period for a page.
You will also need to pip install django-hitcount and add it to your INSTALLED_APPS in settings.py.
As mentioned in another answer, you can add view_count field to your model. Then you can leverage Wagtail's hooks to increment the value in database.
New field in the model:
class BlogPage(Page):
view_count = models.PositiveBigIntegerField(default=0, db_index=True)
Register the before_serve_page hook:
@hooks.register("before_serve_page")
def increment_view_count(page, request, serve_args, serve_kwargs):
if page.specific_class == BlogPost:
BlogPost.objects.filter(pk=page.pk).update(view_count=F('view_count') + 1)
In this approach database takes responsibility to correctly increment view_count so you don't have to worry about locking and incrementing the value yourself.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With