Django admin. Visualización de un filtro desplegable jerárquico

Tengo el siguiente modelo:

from django.db import models class State(models.Model): name = models.CharField(max_length=30) abbreviation = models.CharField(max_length=2) def numberOfCities(self): return self.city_set.count() def __unicode__(self): return u"{0} - {1}".format(self.abbreviation, self.name) class City(models.Model): name = models.CharField(max_length=40) state = models.ForeignKey(State) class Meta: verbose_name_plural = 'Cities' def __unicode__(self): return self.name class Company(models.Model): name = models.CharField(max_length=60) description = models.CharField(max_length=1000) city = models.ForeignKey(City) class Meta: verbose_name_plural = 'Companies' def __unicode__(self): return self.name; 

Como puede ver, cada compañía está asociada con una ciudad y, como era de esperar, el administrador de Django genera el formulario de creación de la empresa que contiene un menú desplegable de ciudades. Pero para mejorar la experiencia del usuario, me gustaría que el usuario seleccione primero el estado y luego el desplegable de la ciudad se rellene con las ciudades de ese estado. ¿Hay una forma estándar de hacer esto?

Debe crear un widget personalizado para elegir el modelo de Ciudad (es decir, su modelo debe FK a Ciudad y no a Estado), este widget contiene dos campos de Selección, el primero contiene los Estados y el segundo se carga en la selección de un estado (deberá conectar una vista para devolver ciudades según la identificación del estado para completar su selección de ciudad).

Debe configurar el punto de clase interno del medio de los widgets para el archivo .js específico que encadena ambas selecciones.

En la especificación ModelAdmin, configure el widget de su campo al widget personalizado que acaba de crear y su medio se agregará automáticamente a la plantilla change_form.

Asegúrese de que su archivo .js busque su objeto JQuery normal y vuelva a django.JQuery, de esta manera puede usar este mismo widget en el administrador y en todo su sitio.

 (function($) { // Note that this function works only for one widget per page $('#state').change(function(){ $('#city').load('/cities_by_state/', {id: this.value}); // the endpoint returns HTML }); })(JQuery||django.JQuery); 

Hice algo similar en una aplicación que uso localmente para mis proyectos (profundidad variable hasta tres niveles) y la solución resultante terminó siendo un poco complicada, ya que tenía que admitir múltiples widgets por página, widgets dynamics (para inlines), tags de plantilla Para renderizar el widget en varias formas, etc.

No es fácil doblar al administrador, pero es solo otra aplicación de django, aunque es realmente compleja. Normalmente hago algo como esto:

  1. Cree una plantilla de administración personalizada para el modelo en cuestión (anule el change_form.html).
  2. Haga una URL de ajax que devuelva el widget de ciudad filtrado por ID de estado.
  3. Use algo como jQuery para reemplazar el widget de la ciudad cuando cambie el estado.

Django admin Javascript ya hace uso de la biblioteca jQuery. Para evitar conflictos con los scripts de los usuarios, jQuery de Django tiene un espacio de nombre como django.jQuery. Para no tener que incluir una segunda copia, puede usar el objeto django.jQuery en la lista de cambios y agregar / editar vistas.