HTMX + Django - 在 HTML 表中编辑 ModelForm

Ali*_*den 3 django htmx

对于 HTMX 和 Django 来说,我想要实现的是在页面上有一个 ModelForm,并带有一个按钮,允许用户直接在页面上“编辑”字段值。按“编辑”按钮后,页面应显示“取消”和“提交”按钮。它与 HTMX 网站上的这个示例基本相同:Edit Row

  • 取消应该放弃编辑并再次显示表格(原样)
  • 提交应该将所做的更改发布回模型中

在索引页查看:

在此输入图像描述


这是我到目前为止所拥有的(当用户按下“编辑条目”时),但它没有按预期工作:

在此输入图像描述

有几个问题:

  1. 当按下“编辑”按钮时,ModelForm 会将所有内容加载到 HTML 表的第一列中。理想情况下,我希望模型的每个字段都位于表中的“正确”位置。

  2. 当按下“取消编辑”按钮时,会将 ModelForm 交换回 HTML 模板。我不想要这个,只是想让表行恢复到以前的状态。

  3. 提交按钮不会将数据发送回模型。


我不确定如何真正考虑这里的设计以使 HTML 表和 ModelForm 按预期工作(#1 和 #2)。

对于#3,问题似乎是 PUT request.method 作为空的 QuerySet 返回。

感谢您提供的任何帮助。一旦我开始工作,我将上传一个简短的视频到 YouTube,以帮助其他初学者,因为除了这个简单的实现的文档之外,我无法在网上找到任何示例。


基本 HTML 模板

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <!-- Bootstrap -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-gH2yIJqKdNHPEq0n4Mqa/HGKIhSkIHeL5AyhkYV8i59U5AR6csBvApHHNl/vI1Bx" crossorigin="anonymous">
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-A3rJD856KowSb7dwlZdYEkO39Gagi7vIsF0jrRAoQmDKKtQBHUuLZ9AsSv4jD4Xa" crossorigin="anonymous"></script>

    <!-- HTMX -->
    <script src="https://unpkg.com/htmx.org@1.8.0" integrity="sha384-cZuAZ+ZbwkNRnrKi05G/fjBX+azI9DNOkNYysZ0I/X5ZFgsmMiBXgDZof30F5ofc" crossorigin="anonymous"></script>

</head>

{% block page_content %}

<body>

    <table class="country_table">
        <thead>
            <tr>
                <th> City Name </th>
                <th> Country </th>
                <th> Latitude </th>
                <th> Longitude </th>
                <th> </th>
            </tr>
        </thead>
        <tbody hx-target="closest tr" hx-swap="outer HTML">
            {% for city in city_model %}
            <tr>
                <td> {{city.city_name}}</td>
                <td> {{city.city_country}}</td>
                <td> {{city.city_latitude}}</td>
                <td> {{city.city_longitude}}</td>
                <td> <button class="btn btn-danger"
                    hx-get="{% url 'edit_city_record' city.city_name %}"
                    hx-trigger="click"> Edit Entry </button> </td>
            </tr>
            {%endfor%}
        </tbody>
    </table>

</body>

{% endblock page_content %}

</html>

<script>
    document.body.addEventListener('htmx:configRequest', (event) => {
    event.detail.headers['X-CSRFToken'] = '{{ csrf_token }}'; })    
</script>
Run Code Online (Sandbox Code Playgroud)

edit_city_record.html 模板

{% extends 'base_html.html' %}

{% block page_content %}

<tr>
    <td> {{city_form.city_name}} </td>
    <td> {{city_form.city_country}} </td>
    <td> {{city_form.city_latitude}} </td>
    <td> {{city_form.city_longitude}} </td>
   
    <td> <button class="btn btn-danger"
        hx-get="{% url 'get_city_record' city_object.city_name %}"
        hx-trigger="click"> Cancel Edit </button> </td>

    <td> 
        <button class="btn btn-danger"
        type="submit"
        hx-put="{% url 'edit_city_record' city_object.city_name %}"
        hx-trigger="click"> Save Edit </button> 

    </td>

</tr>

{% endblock page_content %}
Run Code Online (Sandbox Code Playgroud)

get_city_record.py 模板

{% extends 'base_html.html' %}
{% block page_content %}
     {{city_form}}
{% endblock page_content %}
Run Code Online (Sandbox Code Playgroud)

视图.py

from django.shortcuts import render

from main_app.models import cityModel
from main_app.forms import cityModelForm

def index(request):

    city_model = cityModel.objects.all()

    context = {'city_model': city_model}
    return render(request, 'base_html.html', context)


def edit_city_record(request, city_name):
    print(request.method)
    city_object = cityModel.objects.get(city_name=city_name) 
    
    if request.method == 'PUT':
        city_form = cityModelForm(request.POST, instance=city_object)
        print(request.POST)

        if city_form.is_valid():
            city_form.save()

    else:
        city_form = cityModelForm(instance=city_object)

    context = {'city_form': city_form, 'city_object': city_object}
    return render(request, 'edit_city_record.html', context)


def get_city_record(request, city_name):
    city_object = cityModel.objects.get(city_name=city_name)
    city_form = cityModelForm(instance=city_object)
    context = {'city_form': city_form}
    return render(request, 'get_city_record.html', context) 
Run Code Online (Sandbox Code Playgroud)

oko*_*mar 5

对于编辑行的部分呈现,您不应扩展整个 base.html。这导致了问题 #1 和 #2。这里很好地解释了使用 django 和 htmx 进行部分渲染。

hx-include="closest tr"对于#3,提交您在提交按钮上缺少的数据。请参阅您链接的演示页面并检查提交按钮上的 hx 参数。这样,您的输入将从行中获取,没有它并且没有表单,它只会发出空的 put。