HTMX, Django - обновление части страницы
Я начал работать с HTMX и хочу использовать его для обновления части страницы после нажатия кнопки на всплывающей странице. Кнопка добавляет щелкнувшего пользователя как участника события. Я просматриваю настоящие учебники и примеры, в которых в основном представлены случаи с формами, и я не знаю, как подойти к этому обновлению.
Я почти уверен, что должен использовать hx-ws, но для меня совершенно непонятно, как это сделать.
chall-interface.html (здесь находится часть, которую я хочу обновить)
{% load static %}
{% load tagz %}
<div id='chall-interface' class="card-bottom mb-2">
<button onclick="call('challFollows',{'id':'{{chall.id}}'}, this)" class='icon icon-s rounded-sm float-end background-transparent mb-2 me-1 color-white'><i class="font-12 fa fa-heart {% followedChall user chall %}"></i></button>
<button href="#" data-menu="comment-section" class="icon icon-s rounded-sm float-end background-transparent mx-1 mb-2">
<i class="font-12 fa fa-comments color-white"></i>
</button>
{% if chall.dealine_is_over %}
<button href="#" data-menu="rules" class="icon icon-s rounded-sm float-end background-transparent mx-1 mb-2">
<i class="font-12 fa color-white {% changeJoinButton user chall %}""></i>
</button>
<!-- Here is a code I'm asking about -->
{% if user == userParticipationStatus.user %}
<a href="/addResponse/{{chall.id}}" class="icon icon-s rounded-sm float-end background-transparent mx-1 mb-2">
<i class="font-12 fa fa-plus-square color-white"></i>
</a>
{% else %}
{% endif %}
<!-- Here is a code I'm asking about -->
{% if chall.user == user %}
<button class="icon icon-s rounded-sm float-end background-transparent mx-1 mb-2">
<i class="font-12 fa fa-pen color-white"></i>
</button>
{% else %}
{% endif %}
{% else %}
{% endif %}
<div class="card-bottom mb-1 w-25">
{% if chall.profile.id == None %}
<a href='#'><img src="{% static 'images/avatars/5s.png' %}" class="float-start border border-white bg-yellow-light rounded-circle ms-3" width="35"></a>
{% elif chall.user == user %}
<a href='/profile/'><img src="{% static 'images/avatars/5s.png' %}" class="float-start border border-white bg-yellow-light rounded-circle ms-3" width="35"></a>
{% else %}
<a href='/userProfile/{{chall.profile.id}}'><img src="{% static 'images/avatars/5s.png' %}" class="float-start border border-white bg-yellow-light rounded-circle ms-3" width="35"></a>
{% endif %}
<span class="float-start mx-3"><i>{{chall.profile.nickname}}</i></span>
</div>
</div>
Добавляется как {% include "include/chall-interface.html" %} в основной html файл, из которого активируется всплывающее окно
Вот всплывающее окно
{% load tagz %}
<div id="rules" class="menu menu-box-modal rounded-m" data-menu-width="350">
<div class="card card-style" style="margin: 0px !important">
<div class="content">
<strong class="font-12 mx-1">Rules</strong>
<span class="color-theme font-14 d-block mx-1">{{chall.rules}}</span>
<!-- This is the button -->
<button onclick="call('challParticipates',{'id':'{{chall.id}}'}, this)" class="close-menu btn btn-m float-end rounded-xl shadow-xl text-uppercase font-800 bg-highlight mx-1 my-2"><i>{% changeJoinButton2 user chall %}</i></button>
<!-- This is the button -->
<button data-bs-dismiss="modal" class="close-menu btn btn-m float-end rounded-xl shadow-xl text-uppercase font-800 bg-highlight mx-1 my-2"><i>Exit</i></button>
</div>
</div>
</div>
Вот функция вызова, активируемая кнопкой:
function call(url, info, element) {
eventStatus = false
fetch("/"+url+"/", {
method: 'POST',
headers: {'X-CSRFToken': getCookie('csrftoken')},
body: JSON.stringify(info)
}).then(response => response.text())
.then(responseData => {
dataParsed = JSON.parse(responseData);
console.log(dataParsed)
if (dataParsed.eventStatus) {
element.firstElementChild.classList.add("color-gold");
element.firstElementChild.classList.remove("color-white");
}
else {
element.firstElementChild.classList.remove("color-gold");
element.firstElementChild.classList.add("color-white");
}
})
.catch(err => {
// if any error occured, then catch it here
console.error(err);
});
}
View.py
class ChallView(LoginRequiredMixin, TemplateView):
login_url = '/chalth/login'
redirect_field_name = ''
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
chall = Chall.objects.get(id=kwargs.get("id"))
context['chall'] = chall
currentUser = self.request.user
context['userParticipationStatus'] = Participates.objects.filter(user = currentUser, chall = chall).first()
return context
@login_required(login_url = '/chalth/login')
def ChallParticipatesView(request):
data = json.loads(request.body)
id = data.get("id", False)
if id:
challParticipate = Participates.objects.filter(chall_id=id, user=request.user).first()
eventStatus = False
if challParticipate:
challParticipate.delete()
eventStatus = False
else:
challParticipate=Participates()
chall = Chall.objects.get(id=id)
eventStatus = True
if chall:
challParticipate.chall = chall
challParticipate.user = request.user
challParticipate.save()
else:
return HttpResponse(status = 400)
else:
return HttpResponse(status = 400)
return HttpResponse(json.dumps({"eventStatus": eventStatus, "id": id}), status = 200)
Насколько я могу понять из вашего кода, я не вижу htmx
в действии.
Сначала я предлагаю вам попробовать использовать встроенный способ, например:
<button hx-post="/clicked"
hx-trigger="click"
hx-target="#parent-div"
hx-swap="outerHTML"
>
Click Me!
</button>
чтобы узнать, связана ли ваша проблема с:
- сервер, который не возвращает корректный HTML
- сервер, который возвращает ошибку (которая остановит обмен)
- неправильное использование
htmx
APIs
Также убедитесь, что знаете, какие свойства:
hx-trigger
hx-target
hx-swap
do.
Надеюсь, я помог 😊