2009-05-14 31 views
9

tengo un modelo que tiene un campo denominado "estado":cómo modificar las opciones en las páginas de administración - Django

class Foo(models.Model): 
    ... 
    state = models.IntegerField(choices = STATES) 
    ... 

Para cada estado, las posibles opciones son un cierto subconjunto de todos los estados. Por ejemplo:

if foo.state == STATES.OPEN:  #if foo is open, possible states are CLOSED, CANCELED 
    ... 
if foo.state == STATES.PENDING: #if foo is pending, possible states are OPEN,CANCELED 
    ... 

Como resultado, cuando los cambios foo.state a un nuevo estado, su conjunto de opciones posibles cambios también.

¿Cómo puedo implementar esta funcionalidad en Admin agregar/cambiar páginas?

Respuesta

9

Es necesario use a custom ModelForm en la clase ModelAdmin para ese modelo. En el método __init__ la costumbre de ModelForm, se puede establecer de forma dinámica las opciones para ese campo:

class FooForm(forms.ModelForm): 
    class Meta: 
     model = Foo 

    def __init__(self, *args, **kwargs): 
     super(FooForm, self).__init__(*args, **kwargs) 
     current_state = self.instance.state 
     ...construct available_choices based on current state... 
     self.fields['state'].choices = available_choices 

que tendría que utilizar de esta manera:

class FooAdmin(admin.ModelAdmin): 
    form = FooForm 
+0

Lo que sucede en las vistas de 'agregar' para el administrador, ya que no hay una instancia propia, no puede depender de la instancia para filtrar, sería bueno tener el objeto de solicitud allí –

+0

Sí, este ModelForm debería manejar la ausencia de self.instance y establecer las opciones disponibles iniciales apropiadamente. No sé por qué el objeto de solicitud es relevante, pero usted tiene acceso a él en ModelAdmin.add_view (http://code.djangoproject.com/browser/django/trunk/django/contrib/admin/options.py# L704). –

+0

¿Es posible cambiar las elecciones en el modelo en sí? Después de todo, las elecciones SON inicialmente especificadas en el modelo, al crear el campo. –

-1

Veo lo que estás tratando de hacer, pero ¿por qué no simplemente mostrarlos todos y si la persona elige el estado actual (ya establecido), simplemente no cambies nada?

También puede simplemente construir una visión con una forma de proporcionar esta funcionalidad

+0

es una posibilidad, pero no muy elegante y segura. cambiar el estado desencadena algunos cálculos y modificaciones de los datos que se realizarán, por lo tanto, realmente no quiero confiar en los usuarios, incluso si son administradores. – shanyu

0

Esto parece como un trabajo para algunos javascript. Desea que la lista de elementos en un cuadro de selección cambie dependiendo del valor de otra cosa, que es presumiblemente una casilla de verificación o un botón de opción. La única forma de que esto ocurra dinámicamente, sin hacer que el usuario guarde el formulario y vuelva a cargar la página, sería con javascript.

Puede cargar javascript personalizado en la página de administración de un modelo utilizando la clase de Media de ModelAdmin, documentada here.

+1

No, está tratando de establecer las opciones para el siguiente valor de un campo en función del valor actual de ese mismo campo, una diferencia clave. Entonces, cambiar las opciones dinámicamente desde el lado del cliente no es relevante; de hecho, sería muy confuso. –

12

Cuando crea una nueva interfaz de administrador para un modelo (por ejemplo, MyModelAdmin) existen métodos específicos para anular las opciones predeterminadas de un campo. Para un genérico choice field:

class MyModelAdmin(admin.ModelAdmin): 
    def formfield_for_choice_field(self, db_field, request, **kwargs): 
     if db_field.name == "status": 
      kwargs['choices'] = (
       ('accepted', 'Accepted'), 
       ('denied', 'Denied'), 
      ) 
      if request.user.is_superuser: 
       kwargs['choices'] += (('ready', 'Ready for deployment'),) 
     return super(MyModelAdmin, self).formfield_for_choice_field(db_field, request, **kwargs) 

Pero también se puede anular opciones para ForeignKey y Many to Many relaciones.

+3

Esta debería ser la respuesta aceptada, ya que es la solución más fácil y la mejor. –

+0

@shanyu Esta debería ser la respuesta aceptada ya que es la forma más pitónica de manejar el problema. – Jay

Cuestiones relacionadas