Страница администратора Django выполняет javascript на кнопках пользовательских действий

Я пытаюсь добавить пользовательскую кнопку в каждой строке рядом с пользователем на страницу администратора django, что облегчает администратору нажатие на кнопку и создание ссылки сброса пароля для конкретного пользователя, а не переход в скрытый раздел actions на странице администратора django.

Что-то вроде этого - https://hakibenita.com/how-to-add-custom-action-buttons-to-django-admin

Ниже приведен код, который я реализовал, и он работает и переходит на новую страницу с правильным запросом reset-password и метод reset_password() выполняется с отправкой ссылки пользователю.

Однако, когда я нажимаю на кнопку, я хотел бы отправить AJAX GET запрос на тот же url, что и выше, и просто показать администратору оповещение о завершении запроса вместо перехода на новую страницу. В настоящее время я не могу запустить код javascript, используя метод format_html в Django (см. код ниже)

class UserAdmin(Admin.modelAdmin):
    list_display = ('name', 'email', 'custom_actions')

    form = forms.UserAdminForm
  
    def get_urls(self):
        urls = super().get_urls()
        custom_urls = [
            url(
                r'reset-password/(?P<user_id>.+)',
                self.admin_site.admin_view(self.reset-password),
                name='reset-password',
            ),
        ]
        return custom_urls + urls

    def custom_actions(self, obj):
            user = user_model.User.get(user_id=obj.id)
            password_reset_url = reverse('admin:reset-password', args=[user.id])
            return mark_safe(format_html(
                f'<a class="button" onclick="parent.location=\'{password_reset_url}\'" >Reset Password</a>&nbsp;'
    custom_actions.short_description = 'Custom Actions'
    custom_actions.allow_tags = True


    def reset_password(self, request, password_reset_id):
        password_reset.send_password_reset_link(password_reset_id=password_reset_id)
        return HttpResponse(status=200)

Ниже приведен HTML/JS код, который я тестировал для желаемого поведения на странице и он работает, я надеялся вшить то же самое в вышеприведенный Django код, но Django не может выполнить и просто показывает скрипт как строку на странице администратора.

<button id='jax' class="button">AJAX</button>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script>
  $(document).ready(function() {
    $("#jax").click(function(){
      $.ajax({
        type : "GET",
        url : "my-dynamic-url",
        timeout:10,
        jsonp : "jsonp",
        success : function (response, textS, xhr) {
          console.log('oof')
          alert("Password reset link has been resent");
        },
        error : function (xmlHttpRequest, textStatus, errorThrown) {
          if(textStatus==='timeout')
            alert("request timed out");
        }
      });
    });
  });
</script>

Есть ли правильный способ интегрировать приведенный выше код javascript на страницу администратора по нажатию кнопки?

Не хватает ли запятых? Из примера согласно документации :

format_html("{} <b>{}</b> {}",
    mark_safe(some_html),
    some_text,
    some_other_text,
)

Может быть, вам следует обернуть {password_reset_url} запятыми и посмотреть, сработает ли это.

Если это не решит вашу проблему, будет полезно рассказать об этом подробнее:

Django не может выполнить скрипт и просто показывает его в виде строки на странице администратора.

Какой скрипт вы имеете в виду?

Решение:

Python:

class UserAdmin(Admin.modelAdmin):
    list_display = ('name', 'email', 'custom_actions')

    form = forms.UserAdminForm
  
    def get_urls(self):
        urls = super().get_urls()
        custom_urls = [
            url(
                r'reset-password/(?P<user_id>.+)',
                self.admin_site.admin_view(self.reset-password),
                name='reset-password',
            ),
        ]
        return custom_urls + urls

    def custom_actions(self, obj):
            user = user_model.User.get(user_id=obj.id)
            password_reset_url = reverse('admin:reset-password', args=[user.id])
            return mark_safe(format_html(
                f'<a class="button" onclick="send_password_link(\'{password_reset_url}\'") >Reset Password</a>&nbsp;'
    custom_actions.short_description = 'Custom Actions'
    custom_actions.allow_tags = True


    def reset_password(self, request, password_reset_id):
        password_reset.send_password_reset_link(password_reset_id=password_reset_id)
        return HttpResponse(status=200)

HTML: Это должно быть в разделе base-app/templates/your-app/change_list.html

{% extends "admin/change_list.html" %} 
{% load static %}
{% block content %}
<script src="{% static 'js/passwordReset.js' %}"></script>

<!-- Render the rest of the ChangeList view by calling block.super -->
{{ block.super }} 

{% endblock %}

Javascript: Это должно быть в разделе base-app/static/static/js/passwordReset.js

function send_password_link(url) {
    var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
            alert('Password Reset Sent');
        }
    };
    xhttp.open("GET", url, true);
    xhttp.send();
}
Вернуться на верх