Binayak
Binayak

Reputation: 83

Django Admin, how to populate select options depending on another select

My scenario:

I'm having three tables, Category, Subcategory, Products. While inserting new product, there are two select boxes

1)1st select is for Category (its working)

2) 2nd is for Subcategory, which should be relevant to the 1st select. Needs to fetch the data from subcategory table.

Subcategory table has category id as a foreign key. I am a beginner, please somebody help.

Upvotes: 8

Views: 5460

Answers (3)

reza mahmoudian
reza mahmoudian

Reputation: 1

I thank Mr Satendra for his good answer.

Your answer did not work in Django 4.2 and I made some changes to make it work

views.py

from .models import SubCategory, Category
from django.http import HttpResponse
import json


def get_subcategory(request):
    id = request.GET.get('id', '')
    cat = Category.objects.get(pk=id)
    result = list(SubCategory.objects.filter(category=cat).values('id', 'name'))
    return HttpResponse(json.dumps(result), content_type="application/json")

urls.py

from django.urls import path
from . import views

app_name = 'your app name'

urlpatterns = [
    path('getsubcategory/', views.get_subcategory, name='get-subcategory'),
]

change_form.html

{% extends "admin/change_form.html" %}
{% load static %}

<div> change form connect</div>
{% block extrahead %}
    {{ block.super }}
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    <script type="text/javascript">
        $(function(){
        // inspect html to check id of category select dropdown.
        $(document).on('change', "select#id_category", function(){
            $.getJSON("/getsubcategory/",{id: $(this).val()}, function(j){
                 var options = '<option value="" disabled selected>---------</option>';
                 console.log(j);
                 for (var i = 0; i < j.length; i++) {
                     options += '<option value="' + j[i].id + '">' + j[i].name+ '</option>';
                 }
                 // inspect html to check id of subcategory select dropdown.
                 $("select#id_subcategory").html(options);
             });
         });
     });
    </script>
{% endblock %}

Upvotes: 0

Mobasshir Bhuiya
Mobasshir Bhuiya

Reputation: 1092

url: path('features/',views.get_features,name='features'),
views: def get_features(request):
    id = request.GET.get('id','')
    cat = Category.objects.get(pk=id) 
    result = list(Feature.objects.filter(category=cat).values('id', 'name')) 
    print(result)
    return HttpResponse(json.dumps(result), content_type="application/json") 

javascript:             $(function(){ 
        // inspect html to check id of category select dropdown.
        $(document).on('change', "select#category_select_m1", function(){ 
            $.getJSON("features/",{id: $(this).val()}, function(j){ 
                 var options = '<option value="" disabled selected>Choose your feature</option>'; 
                 console.log(j);
                 for (var i = 0; i < j.length; i++) { 
                     options += '<option value="' + j[i].id + '">' + j[i].name + '</option>'; 
                 } 
                 // inspect html to check id of subcategory select dropdown.
                 $("select#feature_select_m1").html(options); 
             }); 
         }); 
     }); 

Updated for django 2.1 but not working and thanks to Satendra. I can not comment above thats why submitted my problem as answer

Upvotes: 2

Satendra
Satendra

Reputation: 6865

You will have to use some JS library I prefer JQuery.

For filling this subcategory field, you have to create a view which will respond with json data.

from django.http import HttpResponse
import json

def get_subcategory(request): 
    id = request.GET.get('id','') 
    result = list(Subcategory.objects.filter(category_id=int(id)).values('id', 'name')) 
    return HttpResponse(json.dumps(result), content_type="application/json") 

At urls.py you need to add a pattern to reach the view:

url(r'^/getSubcategory/$', views.get_subcategory) 

Now you have to override change_from.html of django admin for your product app to add some JS code to do the magic.

your_project
     |-- your_project/
     |-- myapp/
     |-- templates/
          |-- admin/
              |-- myapp/
                  |-- change_form.html  # do not misspell this

Note: The location of this file is not important. You can put it inside your app and it will still work. As long as its location can be discovered by django. What's more important is the name of the HTML file has to be the same as the original HTML file name provided by django.

In your change_form.html, write somethings like this:

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

{% block extrahead %}
    {{ block.super }} 
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> 
    <script type="text/javascript" charset="utf-8"> 
        $(function(){ 
            // inspect html to check id of category select dropdown.
            $(document).on('change', "select#id_category", function(){ 
                $.getJSON("/getSubcategory/",{id: $(this).val()}, function(j){ 
                     var options = '<option value="">---------</option>'; 
                     for (var i = 0; i < j.length; i++) { 
                         options += '<option value="' + j[i].id + '">' + j[i].name + '</option>'; 
                     } 
                     // inspect html to check id of subcategory select dropdown.
                     $("select#id_subcategory").html(options); 
                 }); 
             }); 
         }); 
    </script>
{% endblock %} 
# Create a JS file and put this second script tag in it, that way will be easier to maintain your template.

Upvotes: 7

Related Questions