我计划在博客网站中创建一个页面,它根据页面浏览量排列和显示所有博客文章。不知道如何拉下来。
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"),
]
如另一个答案中所述,您可以将view_count
字段添加到模型中。然后,您可以利用 Wagtail 的钩子来增加数据库中的值。
模型中的新字段:
class BlogPage(Page):
view_count = models.PositiveBigIntegerField(default=0, db_index=True)
注册before_serve_page
钩:
@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)
在这种方法中,数据库负责正确递增view_count
因此您不必担心自己锁定和递增值。
如果您想以稍微更有特色的方式计算观看次数,您可以使用django-hitcount
包。
然后,您的wagtail_hooks.py
文件将变为:
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)
您需要在Page
定义中添加HitCountMixin
,即
from hitcount.models import HitCountMixin
class BlogPage(Page, HitCountMixin):
这允许您计算命中数,但避免来自同一 IP 的重复,使用管理命令重置命中数,以及设置页面的"活动"周期。
您还需要pip install django-hitcount
并将其添加到settings.py
中的INSTALLED_APPS
中。
作为一个朴素的解决方案,您可以将字段view_count
添加到您的BlogPage
模型中,这将是一个IntegerField
。
您将需要一种方法来在每次提供页面时更新此值,您可以向已使用get_context
方法添加一些逻辑。但是,serve
方法会更合适,请务必通过选中request.is_preview
来检查服务是否未作为预览调用。
关于查询(按此view_count
排序(,这可以通过更新查询来完成。
blogposts = self.get_siblings().live().public().order_by('-view_count')
您可以通过具有自定义widget
的FieldPanel
添加此新字段,使此新字段可见,但不容易编辑(仅限客户端验证(。使用鹡鸰settings_panels
可以在非内容面板中使用它。
示例模型
models.py
from django.db import models
from django import forms
from wagtail.core.models import Page
class BlogPage(Page):
# ... other fields
view_count = models.IntegerField(blank=False, default=0)
content_panels = Page.content_panels + [
# ... existing content panels
]
settings_panels = Page.settings_panels + [
FieldPanel(
'view_count',
# show the view count in the settings tab but do not allow it to be edited
# note: can be easily edited by savvy users, but only if they can also access admin
widget=forms.NumberInput(attrs={'disabled': 'disabled', 'readonly': 'readonly'})
)
]
请注意:此实现不考虑可能调用serve
的任何其他情况,但并不意味着"唯一用户看到了我的博客文章"。你可能想要研究一个合适的Django分析解决方案或与客户端分析(如Google Analytics或Heap(的某种集成。