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.

Надеюсь, я помог 😊

Вернуться на верх