Search code examples
pythondjangodatabasedjango-modelsdjango-admin

Pre populating editable django admin form from other table


this is the django admin panel with a table named Committees

this is the django admin panel with a table named Committees. there is a field named committee type in committees table.

There is a table named default, with the model defined below,

class default(models.Model):
    committee_type = models.CharField()
    description = models.CharField()
    quorum = models.InetgerField()

What i wanted to do is, 1) when i select the committee type to city council in committees table in admin(like in screenshot), I wanted to populate the description and quorum from the default table in to the description and quorum in committees table in the admin itself 2) these populated data should be retrieved from default table where the committee type is city council 3) these fields should be editable in the committees table in admin after getting populated from the default table and should be able to be saved in this committee object

Thanks in advance!


Solution

  • I am the OP, and I have returned with an answer after 7 years of professional experience.

    1. Override the Admin Form: You need to override the default form that ModelAdmin uses for the Committees model and write your own custom form to add functionality.
    2. JavaScript for Dynamic Updates: You need to write JavaScript to listen to the changes in the committee_type field and fire an AJAX request to fetch the data from the default table based on the select committee_type.
    3. Custom View for AJAX: You need to write a custom view in your Django app which is going to handle the AJAX request and return the required data.

    Following is how you can do that in a step-by-step manner:

    Step 1: Override the Admin Form

    Write the custom form for the Committees model:

    from django import forms
    from django.contrib import admin
    from .models import Committees, Default
    
    class CommitteesForm(forms.ModelForm):
        class Meta:
            model = Committees
            fields = '__all__'
    
        class Media:
            js = ('admin/js/committees.js',)
    
    @admin.register(Committees)
    class CommitteesAdmin(admin.ModelAdmin):
        form = CommitteesForm
    

    Step 2: JavaScript for Dynamic Updates

    Write a JavaScript file, say committees.js, to handle the change event on the committee_type field and make an AJAX call to request the data.

    document.addEventListener('DOMContentLoaded', function() {
        const committeeTypeField = document.getElementById('id_committee_type');
        if (committeeTypeField) {
            committeeTypeField.addEventListener('change', function() {
                const committeeType = this.value;
                fetch(`/admin/fetch_default_data/?committee_type=${committeeType}`)
                    .then(response => response.json())
                    .then(data => {
                        if (data) {
                            document.getElementById('id_description').value = data.description;
                            document.getElementById('id_quorum').value = data.quorum;
                        }
                    });
            });
        }
    });
    

    Step 3: Custom View for AJAX

    Add a custom view in your Django app to handle the AJAX request and return the data from the Default table.

    from django.http import JsonResponse
    from django.shortcuts import get_object_or_404
    from .models import Default
    
    def fetch_default_data(request):
        committee_type = request.GET.get('committee_type')
        default_data = get_object_or_404(Default, committee_type=committee_type)
        data = {
            'description': default_data.description,
            'quorum': default_data.quorum,
        }
        return JsonResponse(data)
    

    Step 4: URL Configuration

    Add the custom view in your Django application's urls.py file.

    from django.urls import path
    from .views import fetch_default_data
    
    urlpatterns = [
        # other paths
        path('admin/fetch_default_data/', fetch_default_data, name='fetch_default_data'),
    ]
    

    Following the above steps, you should have a Django admin interface that allows fields to be updated dynamically based on the selection of committee_type, fetching data from another table (Default), and allowing further edits before saving.

    It is good to be back on stack overflow :)