【问题标题】:Django: combine ListView and DeleteView to use with HTMX?Django:将 ListView 和 DeleteView 与 HTMX 结合使用?
【发布时间】:2022-08-22 20:45:37
【问题描述】:

我正在使用 Django 和 HTMX 来管理一个 CRUD 表,我想在其中列出和删除对象。

为此,我有一个 ListView,它显示一个带有分页、排序和文本搜索功能的表格(使用 django-tables)。它与 HTMX 一起按预期工作:例如,如果您转到下一页,则不会重新加载整个页面:HTMX 获取表并上传 DOM 的特定部分。

它看起来像这样:

ListView 的代码如下所示:

class Proposals(SingleTableMixin, SearchableMixin, ListView):
    table_class = ProposalTable # for django-tables2
    ordering = \"id\"
    model = Proposal
    paginate_by = 5
    search_filters = [\"title__icontains\"] # custom text search

    def get_template_names(self):
        # Trick to chose between loading the whole page (first time user goes to the page) or just the table via HTMX (when user uses pagination or sorting, it reloads the table only in the DOM)
        if self.request.htmx:
            return \"fragments/proposals_fragment.html\"
        return \"proposals.html\"

现在,我正在尝试添加一个具有最佳 UX 的删除功能。到目前为止,我已经探索了多种方法:

  1. 一旦从数据库中实际删除对象,只需从 DOM 中删除行 →坏的:虽然它很快,但它会使分页错误/不一致,并且表格页面中的对象较少。

  2. 告诉 HTMX 重定向到当前 url (response[\"HX-Redirect\"] = request.htmx.current_url) →坏的: 虽然最终结果还可以,但速度很慢,用户可以使用 UI 并进行不需要的操作,直到实际发生重定向。当然,我不会从这里的 HTMX 部分 DOM 更新功能中受益。

    所以,我在想第三种听起来更好的方法:

    1. 当用户删除对象时,应该先删除DB中的对象,然后就和HTMX模式下的ListView完全一样(即:返回表页)。这样我就可以使用新的表格页面在本地更新 DOM,而无需重新加载整个页面。

    问题是我不知道如何在 Django 中执行此操作。我很确定我不想与 FBV 混淆,但我需要一些指导。以下是我正在考虑的事情:

    • 使用两个不同的 url (\"proposals\" (GET) 和 \"proposals/int:pk/delete\" (DELETE)) 指向同一个视图
    • 此视图可以是一个名为“ListDeleteView”的自定义视图,将较低级别的 Django mixins 组合在一起,例如 MultipleObjectTemplateResponseMixin + BaseListView + DeletionMixin。或者也许是其他人?

    我在正确的道路上吗?如果这对您来说是个好主意,您能否提供一些指导,尤其是关于如何制作组合的通用视图?

    非常感谢。

    标签: python django django-class-based-views htmx


    【解决方案1】:

    您要做的是在Proposals 列表视图上实现delete 方法,DeleteMixin 实现非常简单,因此您可以使用它并拥有如下内容:

    class Proposals(SingleTableMixin, SearchableMixin, DeletionMixin, ListView):
        table_class = ProposalTable # for django-tables2
        ordering = "id"
        model = Proposal
        paginate_by = 5
        search_filters = ["title__icontains"] # custom text search
    
        def get_template_names(self):
            if self.request.htmx and not self.request.htmx.history_restore_request:
                return "fragments/proposals_fragment.html"
            return "proposals.html"
    
        def delete(self, request, *args, **kwargs):
            super().delete(request, *args, **kwargs)
            return super().get(request, *args, **kwargs)
    

    在这里,您覆盖删除,让它播放,然后返回结果,因为它是正常的获取而不是重定向。而且您还想处理htmx.history_restore_request 我也添加了这一点。

    【讨论】:

      猜你喜欢
      • 2017-05-08
      • 2022-01-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-04
      • 2019-09-22
      相关资源
      最近更新 更多