创建对象并将其显示在与 htmx 相同的页面中

Create object and display it in same page with htmx

我想实现的功能是,当在创建视图中提交表单时,我希望在不刷新页面的情况下将创建的对象显示在其下方。我知道实现这个的方法是通过 HTMX。正在创建的对象是一个唯一且随机生成的密钥。但是它不能正常工作。现在,第一次单击按钮时,它会创建一个键并显示它,但第二次它会尝试显示前一个键,因为它已经存在,所以它不是唯一的,因此它什么都不显示。

这是模型

class Key(models.Model):
    key = models.CharField(max_length=10, null=False, default=get_random_string(length=10), unique=True)
    amount = models.IntegerField(default=1)
    created = models.DateTimeField(auto_now_add=True)

    def get_absolute_url(self):
        return reverse("key", kwargs={"id": self.id })

我有两个视图,一个创建视图和一个详细视图,我本来想使用 CBV,但我不知道如何实现它,所以我坚持使用基于函数的视图。现在的观点是这样的

@login_required
def key_create_view(request):
    form = CreateKeyForm(request.POST or None)

    context = {
        "form": form,
    }
    if form.is_valid():
        obj = form.save(commit=False)
        obj.save()
        key_url = reverse('key', kwargs={'id':obj.id})
        if request.htmx:
            context = {
                 "object": obj,
                 "key_url": key_url
             }
            return render(request, "base/components/key.html", context)
        #return redirect(obj.get_absolute_url())
    return render(request, "base/form.html", context)  



@login_required
def key_detail_hx_view(request, id=None):
    if not request.htmx:
        raise Http404
    try:
        obj = Key.objects.get(id=id)
    except:
        obj = None
    if obj is  None:
        return HttpResponse("Something went wrong")
    context = {
        "object": obj
    }
    return render(request, "base/components/key.html", context) 

我在模板中是这样构建的

<form action="" method="POST">
            {% csrf_token %}
            <div id="key" class="text-center">
                <button hx-post="{{key_url}}" hx-target="#key" hx-swap="beforeend" type="submit">Create new key</button>
            </div>
        </form>

我希望它在每次按下按钮时生成一个新密钥并替换之前的密钥。有人知道我该如何实现吗?

编辑 这些是我的网址

path('createkey', key_create_view, name='create_key'),
    path('createkey/<int:id>', key_detail_hx_view, name='key')

这是表格

class CreateKeyForm(forms.ModelForm):
    class Meta:
        model = Key
        fields = ()

所以它是一个空窗体,只是为了创建对象。

创建表单的 hx-post 端点应该是 key_create_view 而不是显示视图的关键。实际上,表单页面 {{ key_url }} 是空的。此外,由于您只想显示最后生成的密钥,因此交换方法应该是默认的 innerHTML,因此 HTMX 会将 #key div 中的内容替换为新的。

<form action="" method="POST">
  {% csrf_token %}
  <div class="text-center">
    <button hx-post="{% url 'create_key' %}" hx-target="#key" type="submit">Create new key</button>
  </div>
</form>

<!-- HTMX will swap the returned key here -->
<div id="key"></div>

编辑:

重复键错误是由于添加动态默认值的方法不对造成的。如果您实际调用该函数 (get_random_string(10)),它将执行一次并且每个键将收到相同的随机字符串。您需要将该函数作为引用传递,因此每次 Django 创建一个新模型时,它都会调用该函数,创建一个新的随机字符串。由于 get_random_string 需要一个参数,我们需要创建一个小的包装函数。

def get_default_random_string():
    return get_random_string(length=10)


class Key(models.Model):
    key = models.CharField(max_length=10, null=False, default=get_default_random_string, unique=True)
    amount = models.IntegerField(default=1)
    created = models.DateTimeField(auto_now_add=True)