'Create object and display it in same page with htmx
The function I am trying to implement is that, when the form is submitted in the create view, I would like to display the created object beneath it without the page refreshing. I know the way to implement this is through HTMX. The object that is being created is a key which is unique and gets randomly generated. However it does not work properly. Right now, first time clicking the button it creates a key and displays it but the second time it tries to show the previous key and because it already exists it is not unique and therefore it shows nothing.
This is the model
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 })
I have two views, a create view and a detail view, I would have liked to used CBV but I can't get my head around how I would implement that, so I am sticking to function based views. Right now the views are looking like this
@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)
In the template have I built it like this
<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>
I would like it to generate a new key each time the button is pressed and replace the previous one. Does anybody know how I can implement that?
EDIT These are my urls
path('createkey', key_create_view, name='create_key'),
path('createkey/<int:id>', key_detail_hx_view, name='key')
This is the form
class CreateKeyForm(forms.ModelForm):
class Meta:
model = Key
fields = ()
So it is an empty form, just to create the object.
Solution 1:[1]
I would suggest not raising an ABORT but instead using
@Insert
suspend fun insertEntity(entity: Entity): Long
@Update
suspend fun updateEntity(entity: Entity): Int
@Transaction
suspend fun insertOrUpdateEntities(entities: List<Entity>) {
entities.forEach { entity ->
if (insertEntity(entity) < 1) {
updateEntity(entity)
}
}
}
- by default @Insert has onConflictStrategy.IGNORE, so PRIMARY KEY, UNIQUE, NULL and CHECK conflicts will be ignored.
- the @Insert method can return a long (the rowid of the inserted row, or -1 if the row was not inserted), so obtaining that can be used to determine whether or not the row was inserted.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | MikeT |
