2011-03-23 18 views
10

Tengo un modelo que quiero que el personal pueda editar hasta la fecha del evento. De esta manera:Hacer las líneas condicionales en el administrador de Django

class ThingAdmin(admin.ModelAdmin): 
    model = Thing 

    if obj.date < today: #Something like that 
     inlines = [MyInline,] 

El problema es que no tengo acceso a la instancia obj en este nivel. Intenté reemplazar a get_formset(), pero no llegué a ningún lado.

¿Desea asesorar?

Respuesta

9

Gracias a los comentarios de un cambio en 1.4. Mi implementación aquí tampoco era segura para subprocesos, por lo que realmente debería haber sido eliminada.

Dado que get_formsets se pasa el objeto y llama al get_inline_instances, podemos modificar ambas funciones para que actúen sobre el objeto.

Esto debería funcionar:

class ThingAdmin(admin.ModelAdmin): 
    model = Thing 

    inlines = [inline] 
    other_set_of_inlines = [other_inline] 

    def get_inline_instances(self, request, obj=None): 
     #         ^^^ this is new 
     inline_instances = [] 

     if obj.date > datetime.date(2012, 1, 1): 
      inlines = self.inlines 
     else: 
      inlines = self.other_set_of_inlines 

     for inline_class in inlines: 
      inline = inline_class(self.model, self.admin_site) 
      if request: 
       if not (inline.has_add_permission(request) or 
         inline.has_change_permission(request) or 
         inline.has_delete_permission(request)): 
        continue 
       if not inline.has_add_permission(request): 
        inline.max_num = 0 
      inline_instances.append(inline) 
     return inline_instances 

    def get_formsets(self, request, obj=None): 
     for inline in self.get_inline_instances(request, obj): 
      #           ^^^^^ this is new 
      yield inline.get_formset(request, obj) 
+1

Funciona sin problemas. Gracias. –

+0

Esto no funciona desde Django 1.4. '__init__' ya no parece crear self.inline_instances, pero ahora hay un método get_inline_instances() que puedes anular explícitamente. – Cerin

+0

Parece que el comentario de Cerin está desactualizado ya que esta respuesta se ha modificado para usar get_inline_instances –

2

En versión reciente de Django, tendrá que anular ModelAdmin.get_formsets. p.ej.

class MyAdmin(admin.ModelAdmin): 

    def get_formsets(self, request, obj=None): 
     if obj: 
      for _ in super(MyAdmin, self).get_formsets(request, obj): 
       yield _ 
     else: 
      for inline in self.get_specific_inlines(request): 
       yield inline.get_formset(request, obj) 
2

que tenía un caso complejo en el que las soluciones que intentaron fracasaron de manera inesperada (problemas con los campos de sólo lectura en inline). Esta es la manera más clara y prueba de fallos que he encontrado:

class MyAdmin(admin.ModelAdmin): 

    def add_view(self, request, form_url='', extra_context=None): 
     self.inlines = [InlineA, InlineC] 
     return super(MyAdmin, self).add_view(request, form_url, extra_context) 

    def change_view(self, request, object_id, form_url='', extra_context=None): 
     self.inlines = [InlineB, InlineC, InlineD] 
     return super(MyAdmin, self).change_view(request, object_id, form_url, extra_context) 

Esto está trabajando en Django 1.4.x.

0

Tuve una situación en la que necesitaba mostrar una Inline basada en el sitio de administración en el que estaba para una historia determinada.

que era capaz de conseguir inlines dinámicas de trabajo de Django 1.3 utilizando el siguiente código:

En aspectos más destacados/admin.py

class HighlightInline(generic.GenericTabularInline): 
    model = Highlight 
    extra = 1 
    max_num = 4 
    fields = ('order', 'highlight') 
    template = 'admin/highlights/inline.html' 

class HighlightAdmin(admin.ModelAdmin): 
    def regulate_highlight_inlines(self): 
     highlights_enabled = Setting.objects.get_or_default('highlights_enabled', default='') 
     highlight_inline_instance = HighlightInline(self.model, self.admin_site) 
     highlight_found = any(isinstance(x, HighlightInline) for x in self.inline_instances) 
     if highlights_enabled.strip().lower() == 'true': 
      if not highlight_found: 
       self.inline_instances.insert(0, highlight_inline_instance) 
     else: 
      if highlight_found: 
       self.inline_instances.pop(0) 
     print self.inline_instances 

    def change_view(self, request, object_id, form_url='', extra_context=None): 
     self.regulate_highlight_inlines() 
     return super(HighlightAdmin, self).change_view(request, object_id) 

    def add_view(self, request, form_url='', extra_context=None): 
     self.regulate_highlight_inlines() 
     return super(HighlightAdmin, self).add_view(request, form_url, extra_context) 

En la historia/admin.py

class StoryAdmin(HighlightAdmin): 

Una cosa a tener en cuenta es que no estoy meramente manipulando las clases en línea (HighlightInline) sino más bien, estoy cambiando las instancias en línea (HighlightInline (self.model, self.admin_site)). Esto se debe a que django ya ha creado una lista de instancias en línea basadas en una lista de clases en línea durante la construcción inicial de la clase de administrador.

0

Creo que la forma más fácil de cortar este es llamar a su Funciton costumbre en get_fields, o get_fieldsets y así sucesivamente, acaba de establecer self.inlines en una función personalizada.

class XXXAdmin(admin.ModelAdmin): 
    def set_inlines(self, request, obj): 
     """ hack inlines models according current request.user or obj """ 
     self.inlines = [] 
     if request.user.is_superuser or request.user is obj.recorder: 
      self.inlines = [AbcInline, ] 

    def get_fields(self, request, obj=None): 
     self.set_inlines(request, obj) # NOTICE this line 
     super(XXXAdmin, self).get_fields(request, obj) 
0

La forma más llave en mano para hacer esto ahora es anular y super llamada a get_inline_instances.

class ThingAdmin(models.ModelAdmin): 
    inlines = [MyInline,] 

    def get_inline_instances(self, request, obj=None): 
     unfiltered = super(ThingAdmin, self).get_inline_instances(request, obj) 
     #filter out the Inlines you don't want 
     keep_myinline = obj and obj.date < today 
     return [x for x in unfiltered if not isinstance(x,MyInline) or keep_myinline] 

Esto pone MyInline cuando usted lo desea y no cuando no lo hace. Si sabe que el único en línea que tiene en su clase es MiInline, puede hacerlo aún más simple:

class ThingAdmin(models.ModelAdmin): 
    inlines = [MyInline,] 

    def get_inline_instances(self, request, obj=None): 
     if not obj or obj.date >= today: 
      return [] 
     return super(ThingAdmin, self).get_inline_instances(request, obj) 
Cuestiones relacionadas