创建对象并将其显示在与 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)
我想实现的功能是,当在创建视图中提交表单时,我希望在不刷新页面的情况下将创建的对象显示在其下方。我知道实现这个的方法是通过 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)