【问题标题】:django-filters and HTMX: Trigger a Filter on Multiple Views at Oncedjango-filters 和 HTMX:一次在多个视图上触发过滤器
【发布时间】:2022-09-23 04:52:37
【问题描述】:

我有一个简单的应用程序,我想让一个过滤器同时在两个不同的视图中动态更新查询集。

在此示例中,用户可以根据城市/国家/大陆进行过滤,并且我希望动态更新 (1) 显示模型中相关对象的表格,以及 (2) 用于绘制点的传单地图。


我认为这里的主要问题是我需要同时触发对多个“视图”上的过滤器查询集的更新,并且不确定如何构建我的项目来实现这一点。或者,如果那是思考问题的正确方法。

我试图让过滤器同时在两个不同的视图中使用{% for city in cityFilterResults %} 迭代器。

如何实现基于使用 HTMX 的过滤器更新两个不同的视图?


index.html:

(注意:如果我在表格或地图之间切换hx-get URL,我的预期行为会起作用。但它们不会一起过滤,这是我遇到的问题。)

<body>

<h3>Filter Controls:</h3><br>
<form hx-get=\"{% url \'_city_table\' %}\" hx-target=\"#cityTable\">   
<!-- <form hx-get=\"{% url \'_leaflet\' %}\" hx-target=\"#markers\">    -->
    {% csrf_token %}
    {{ cityFilterForm.form.as_p }}
    <button type=\"submit\" class=\"btn btn-primary\"> Filter </button>
</form>

[...]

<!-- Table Body -->
<tbody id=\"cityTable\" hx-get=\"{% url \'_city_table\' %}\" hx-trigger=\"load\" hx-target=\"nearest tr\"> </tbody>

[...]

<!-- Div to get the markers -->
<div id=\"markers\" hx-get=\"{% url \'_leaflet\' %}\" hx-trigger=\"my_custom_trigger from:body\"> </div>

</body>
<script>
[... Leaflet stuff ...]
document.getElementById(\'markers\');
</script>

_city_table.html:

{% for city in cityFilterResults %}

<tr>
    <td> {{ city.city }} </td>
    <td> {{ city.country }} </td>
    <td> {{ city.continent }} </td>
    <td> {{ city.latitude|floatformat:4 }} </td>
    <td> {{ city.longitude|floatformat:4  }} </td>
</tr>

{% endfor %}

_leaflet.html:

<script>

if (map.hasLayer(group)) {
    console.log(\'LayerGroup already exists\');
    group.clearLayers();
    map.removeLayer(group);
} else {
    console.log(\'LayerGroup doesn\'t exist\');
}


{% for city in cityFilterResults %}
    var marker = L.marker([{{city.latitude}}, {{city.longitude}}]).addTo(group)
    .bindPopup(\"{{city.city}}\")
{% endfor %}

group.addTo(map);
</script>

views.py

def _city_table(request):

    city_filter_form = cityFilter(request.GET, queryset=cityModel.objects.all())
    city_filter_results = city_filter_form.qs

    context={   \'cityModel\': cityModel.objects.all(),
                \'cityFilterResults\': city_filter_results }
    
    response = render(request, \'_city_table.html\', context)
    response[\'HX-Trigger\'] = \'my_custom_trigger\'
    return response

def _leaflet(request):

    city_filter_form = cityFilter(request.GET, queryset=cityModel.objects.all())
    city_filter_results = city_filter_form.qs

    context={   \'cityModel\': cityModel.objects.all(),
                \'cityFilterResults\': city_filter_results }
    return render(request, \'_leaflet.html\', context)

当过滤器表单上的 hx-get 指向 _city_table 模板的 URL 时,表格会按预期过滤,但地图不会:

当过滤器表单上的hx-get 指向_leaflet 模板的URL 时,地图会过滤,但表格不会:

    标签: django django-filter htmx


    【解决方案1】:

    你可以在这里找到一些解决方案: https://htmx.org/examples/update-other-content/

    特别是有两种解决方案

    交换oob( https://htmx.org/examples/update-other-content/#oob)

    您必须将表单发布到控制器的操作中。 该动作返回将被替换的两个元素

    <button hx-get="/Form/OutOfBandResponse" hx-swap="none">ok</button>
    
    <div id="A"></div>
    
    <div id="B"></div>
    

    这是回应:

    <!-- this will replace the element with id A -->
    <div id="A" hx-swap-oob="true">
        Joe Smith
    </div>
    
    <!-- this will replace the element with id B -->    
    <div id="B" hx-swap-oob="true">
        Antony Queen
    </div>
    

    或者,您可以使用事件。(https://htmx.org/examples/update-other-content/#events)

    因此,您必须为事件创建一个处理程序,然后当您提交表单时,您必须使用触发该事件的标头进行响应。 当事件触发时,div 会做出更新自己的反应。

    【讨论】:

    • 谢谢!看起来我已经在我的答案中使用了“事件”方法。我检查了 OOB 并观看了一段视频,并且看起来它可以解决我的用例。谢谢,马可。
    【解决方案2】:

    我正在分享我的问题的解决方案。它有效,这很棒,但我非常想了解可以实施哪些替代方法。我的方法感觉像一个黑客,并认为我错过了一些东西。


    我能够使用session 在视图之间传递过滤器。基本上,我使用的是桌子上的过滤器表单。在表的“视图”中,发生了两件事:(1) 我创建了一个 session 并存储过滤结果,以及 (2) 返回一个 HTTP 响应,其中包含一个用作 HTMX 触发器的标头传单部分。

    在 HTML 模板中,我有 Leaflet URL 等待自定义 HTMX 触发器与表格一起返回。然后,在 Leaflet 视图中,我从session 获取数据。


    views.py:

    def _city_table(request):
    
        city_filter_form = cityFilter(request.GET, queryset=cityModel.objects.all())
        city_filter_results = city_filter_form.qs
    
    
        request.session['my_city_filter'] = [city.id for city in city_filter_results] 
        request.session.modified=True
    
    
        context={   'cityModel': cityModel.objects.all(),
                    'cityFilterResults': city_filter_results }
        
        response = render(request, '_city_table.html', context)
        response['HX-Trigger'] = 'my_custom_trigger'
        return response
    
    def _leaflet(request):
    
        city_filter_results = [cityModel.objects.get(id=id) for id in request.session['my_city_filter']]
    
        context={   'cityModel': cityModel.objects.all(),
                    'cityFilterResults': city_filter_results }
        return render(request, '_leaflet.html', context)
    

    index.html:

    <div id="markers" hx-get="{% url '_leaflet' %}" hx-trigger="my_custom_trigger from:body"> </div>
    

    【讨论】:

      猜你喜欢
      • 2021-09-24
      • 2011-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-07
      • 1970-01-01
      • 2013-11-12
      相关资源
      最近更新 更多