skip to Main Content

I’m trying to add a custom button in each row next to a user to the django admin page which makes it easier for the admin to click the button and generate a password reset link for a particular user rather than navigate to the hidden actions section of the django admin page.

Something like this – https://hakibenita.com/how-to-add-custom-action-buttons-to-django-admin

Following is the code I’ve implemented and it works and navigates to a new page with the correct reset-password request and the reset_password() method executes with a link being sent to the user.

However, when I click the button, I would like to send an AJAX GET request to the same url as above and just a show an alert to the admin on request completion instead of navigating to a new page. Currently I’m unable to run the javascript code using the format_html method in Django (see code below)

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)

Below is the HTML/JS code that I was testing for the behavior I want on the page and works, I was hoping to the stitch the same into the above Django code but Django cannot execute and just shows the script as a string on the admin page.

<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>

Is there a correct way to integrate the above javascript code on admin page on the click of the button?

2

Answers


  1. Chosen as BEST ANSWER

    The solution:

    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: This should be under 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: This should be under 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();
    }
    

  2. Are you missing out on commas? From an example according to the documentation:

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

    Maybe you should wrap {password_reset_url} in commas and see if that works.

    If this does not solve your problem, elaborating on this will be helpful:

    Django cannot execute and just shows the script as a string on the admin page.

    Which script are you referring to?

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search