Home > other >  How to access server data in a javascript file that is loaded by Django admin pages
How to access server data in a javascript file that is loaded by Django admin pages

Time:10-27

I need to access server data in a javascript file that gets loaded with an admin page. In my case, I'll need a json variable that is set in the settings.py file (in the production version, this json-variable gets loaded from env-variable which means that the content of the variable is known at startup-time but is not hard coded).

I use the javascript to validate and populate some fields in an admin-page - that is a better UX than doing it server side.

Is it possible to add script-tag to the admin html-pages' head section, that contains server data, i.e. non-static data?

CodePudding user response:

If I understood your question correctly, you need to send some data to the admin from the website, and yes there are multiple ways to do so

  • make an API that serves the data and fetch it using ajax from the admin
  • add the data in the context of the page and use it directly in the admin

in both ways you'll need to edit the admin and add some js code to it so that's what I'll show you here

Editing the admin

First Approch

here we gonna create a js file in the static files and then import it using the js variable in the Media class in the admin

class TestAdmin(admin.ModelAdmin):

      class Media:

          js = ('js/some_js_file.js',)

Second Approach

we will extend the add form template and write the js code directly in the template

    {% extends 'admin/change_form.html' %}
    {% block extrahead %}{{ block.super }}
     # write code here
    {% endblock %}

and in the admin

    class TestAdmin(admin.ModelAdmin):
        add_form_template = 'path_to_template'

note: you will need to enable the templates in the settings

now if you don't like the API approach, you could overwrite the admin add_form function and add the context you need

class TestAdmin(admin.ModelAdmin):
    add_form_template = 'admin/test_form_Change.html'


    def changeform_view(self, request, object_id=None, form_url='', extra_context=None):
        extra_context = extra_context or {}
        extra_context['some_data'] = 'value'
        return super(TestAdmin, self).changeform_view(request, object_id, extra_context=extra_context)

and you could use this tag to add the data to the template

CodePudding user response:

The answer from Mina Atef helped me to get this working. Thanks Mina Atef.

Here is the exact code that I used, in case if it helps someone. This works in Django 4.1. I needed this in list view but you can also use this approach in detail view.

Adding to the admin class:

class PlaceNameAdmin(admin.ModelAdmin):
    # A lof of code not shown

    class Media:
        # Adding the javascript file
        js = ('multi_line_list_edit.js',)

    def changelist_view(self, request, extra_context=None):
        extra_context = extra_context or {}
        # Adding the extra context. It comes from settings but it can be any dynamic data.
        # The REGISTER_PLACES_SETTINGS is actually not static, since it comes 
        # from env-variable that is set in production docker environment.
        extra_context['register_places_settings'] = settings.REGISTER_PLACES_SETTINGS
        return super(PlaceNameAdmin, self).changelist_view(request, extra_context)

A file named change_list.html needs to be added to the templates/admin/ directory. See the django doc for more info on how to override admin templates.

{% extends "admin/change_list.html" %}

{% block extrahead %}
{{ block.super }}

{% comment %}
See docs.djangoproject.com/en/4.1/ref/templates/builtins/#json-script for doc on how to use json_script
{% endcomment %}
{{ register_places_settings|json_script:"register_places_settings" }}
{% endblock %}

Here is how the data get used in multi_line_list_edit.js. This javascript file needs to be placed in the static/ directory.

$(document).ready(function() {
    
    const register_places_settings = JSON.parse(document.getElementById('register_places_settings').textContent);
    // A lof of code not shown
    
});    
  • Related