【问题标题】:Creating a Blogpost Like/Dislike Button within Django/Wagtail在 Django/Wagtail 中创建博客文章的喜欢/不喜欢按钮
【发布时间】:2021-08-07 20:32:41
【问题描述】:

我是 Django 和 Wagtail 的新手,并且一直在寻找一种方法来使用 Wagtail 在博客条目页面上实现“简单”的喜欢/不喜欢按钮。

我在我的页面模型中包含了一个 total_likes IntegerField,并希望在用户单击 html 模板上的按钮时在数据库中增加或减少这个 int。

用户不应该登录。我发现的大多数教程只针对注册用户处理这个问题,这不是我想要的。

如果有人能指出我正确的方向,我会很高兴。 models.py 代码如下。

我不明白如何从模板中调用函数。

    class BlogEntry(Page):
        date = models.DateField("Post date")
        intro = models.CharField(max_length=250, blank=False)
        body = RichTextField(blank=True)
        tags = ClusterTaggableManager(through=BlogEntryTag, blank=True)
        categories = ParentalManyToManyField('blog.BlogCategory', blank=False)
        total_likes = models.IntegerField(blank=False, default=0)
        image = models.ForeignKey(
            "wagtailimages.Image",
            null=True,
            blank=True,
            on_delete=models.SET_NULL,
            related_name="+"
        )
        streamBody = StreamField([
            ("text", blocks.StaticContentBlock()),
            ("quotes", blocks.QuoteBlock()),
            ("image_and_text", blocks.ImageTextBlock()),
            ("related_articles", blocks.RelatedArticlesBlock()),
            ], null=True, blank=True)
    
        sidebarBody = StreamField([
            ("text", blocks.StaticContentBlock()),
            ("quotes", blocks.QuoteBlock()),
            ("image_and_text", blocks.ImageTextBlock()),
            ("related_articles", blocks.RelatedArticlesBlock()),
            ], null=True, blank=True)
    
    
        search_fields = Page.search_fields + [
            index.SearchField('intro'),
            index.SearchField('body'),
        ]
    
        content_panels = Page.content_panels + [
            MultiFieldPanel([
                ImageChooserPanel("image"),
                FieldPanel('date'),
                FieldPanel('tags'),
                FieldPanel('categories', widget=forms.CheckboxSelectMultiple),
            ], heading="Blog information"),
            FieldPanel('intro'),
            StreamFieldPanel("streamBody"),
        ]
    
    
        sidebar_panels = [
            MultiFieldPanel([
                FieldPanel("sidebarBody"),
                ], heading="Sidebar Content")
            ]
    
        edit_handler = TabbedInterface(
            [
                ObjectList(content_panels, heading="Custom"),
                ObjectList(Page.promote_panels, heading="Promote"),
                ObjectList(Page.settings_panels, heading="Settings"),
                ObjectList(sidebar_panels, heading="Sidebar"),
            ]
        )
    
    
        def __str__(self):
            return self.total_likes
    
        def likePost(self):
            self.total_likes += 1
    
        def dislikePost(self):
            self.total_likes -= 1

【问题讨论】:

    标签: html django wagtail


    【解决方案1】:

    概述

    欢迎来到 Django 和 Wagtail,有很多东西要学,但希望你会觉得它很有趣。首先要了解的是网站(浏览器/客户端)如何与服务器通信(运行 Django/Wagtail 的 Python 代码)。即使您的Page 模型具有likePost 方法,您仍需要为您的Page 提供一种方法来处理此类请求。

    网络使用HTTP请求系统,最常见的是GETPOST,其中GET用于拉取数据显示给用户,POST用于网站需要时将内容发送回服务器。

    Django 在working with forms 上的文档可能是开始更多地了解这个过程的好地方。一旦您的网站有 form(在 HTML 模板中),您就可以在提交时提供一种“收听”此表单的方法。 Wagtail 有一个存在于所有 Page 模型上的方法,称为 serve,它允许您覆盖正常行为。

    解决方案

    在下面的解决方案中,您需要执行以下操作:

    1。将两个forms 添加到您的模板(例如blog_page.html

    • 记得加载标签wagtailcore_tags,这样你就可以在表单中访问页面的URL了。
    • 为简单起见,我们创建了两种表单,一种带有用于表示喜欢的按钮,另一种带有用于表示不喜欢的按钮。
    • 两种形式都将使用method="POST",而操作(这是要发布到的 URL)是当前 URL。
    • 每个表单都包含一个csrf_token,您可以在 Django 文档中阅读更多相关信息,但这有助于避免一些安全问题。
    • 每个表单都包含一个带有名称和值的hidden html input,我们将仅在服务器代码中使用name 来确定单击了哪个按钮。
    {% extends "base.html" %}
    {% load wagtailcore_tags %}
    ... BLOG CONTENT
        <form action="{% pageurl page %}" method="POST" role="form">
            {% csrf_token %}
            <input type="hidden" name="like" value="true">
            <input type="submit" value="LIKE">
        </form>
        <form action="{% pageurl page %}" method="POST" role="form">
            {% csrf_token %}
            <input type="hidden" name="dislike" value="true">
            <input type="submit" value="DISLIKE">
        </form>
    

    2。覆盖 Page 模型中的 serve 方法

    Page 模型上的serve 方法采用参数request,即Django request object 并应返回响应。值得庆幸的是,我们不必考虑这个响应是如何构建的,只需知道我们必须在任何逻辑之后调用它的 super(原始)版本。

    • 检查当前请求是否为POST请求,如果是,则检查提交了什么样的值,根据值调用匹配的Page方法
    • 更新likePostdislikePost 方法以确保模型数据通过self.save() 保存
        class BlogEntry(Page):
        # ...
    
        def likePost(self):
            self.total_likes += 1
            self.save() ## note: you may need to ensure you call save to update data
    
        def dislikePost(self):
            self.total_likes -= 1
            self.save() ## note: you may need to ensure you call save to update data
    
        def serve(self, request):
            if request.method == 'POST':
                if request.POST.get('like'):
                    self.likePost()
                    # a form POST has been submitted with a value for 'like'
                if request.POST.get('dislike'):
                    # a form POST has been submitted with a value for 'dislike'
                    self.dislikePost()
            
            # ensure we call the super's serve method so that the page loads correctly
            return super(BlogPage, self).serve(request)
    
    
    

    很高兴知道

    • 正如您所指出的,这是一个基本请求,不需要身份验证(登录)即可提交喜欢,但是您很可能会通过这种方式收到大量垃圾邮件,您可能需要考虑其他方法(甚至第三方系统)来解决这个问题。
    • 这种存储喜欢的方式(作为整数)也不会为您提供太多数据,只是当前时间点的一个数字,可能值得跟踪个人提交,然后向 UI 提供一个计数。
    • 这是来自 MDN 的一个很棒的 overview of HTTP,我发现它是了解服务器如何处理请求和响应的一个很好的参考。

    【讨论】:

    • 非常感谢您的详细解答!真的很感激。我已经开始阅读有关 HTTP、表单和 DRF 的内容——这里可能不需要,但在学习的后期阶段,无论如何我肯定需要研究一些东西。至于垃圾邮件,无论如何,这个系统并不打算上网。我的目标是隔离这个简单的问题,解决它并通过以后添加身份验证等来构建它。我首选的学习方式是孤立地解决小问题。再次感谢您的回答和您的时间!干杯!
    • 没问题,很高兴听到它有帮助。
    猜你喜欢
    • 1970-01-01
    • 2012-09-26
    • 2012-09-20
    • 2014-09-21
    • 2016-04-04
    • 2019-07-03
    • 1970-01-01
    • 2019-01-27
    • 1970-01-01
    相关资源
    最近更新 更多