2011-11-28 8 views
12

Esa pregunta puede tener un aspecto similar a this one, pero no es ...Anulación ahorrar en Django InlineModelAdmin

que tienen una estructura de modelo como:

class Customer(models.Model): 
    .... 

class CustomerCompany(models.Model): 
    customer = models.ForeignKey(Customer) 
    type = models.SmallIntegerField(....) 

estoy usando InlineModels, y tienen dos tipos de CustomerCampany.type. Así que definir dos línea diversa para la CustomerCompany y OV de anulación InlineModelAdmin.queryset

class CustomerAdmin(admin.ModelAdmin): 
    inlines=[CustomerCompanyType1Inline, CustomerCompanyType2Inline] 


class CustomerCompanyType1Inline(admin.TabularInline): 
    model = CustomerCompany 
    def queryset(self, request): 
     return super(CustomerCompanyType1Inline, self).queryset(request).filter(type=1) 

class CustomerCompanyType2Inline(admin.TabularInline): 
    model = CustomerCompany 
    def queryset(self, request): 
     return super(CustomerCompanyType2Inline, self).queryset(request).filter(type=2) 

Todo es agradable y bueno hasta aquí, pero para añadir nuevos registros para InlineModelAdmin, todavía tengo que mostrar type campo de la CustomerCompany en el AdminForm, ya que no puedo anular save método de un InlineModelAdmin gustar:

class CustomerCompanyType2Inline(admin.TabularInline): 
    model = CustomerCompany 
    def queryset(self, request): 
     return super(CustomerCompanyType2Inline, self).queryset(request).filter(type=2) 
    #Following override do not work 
    def save_model(self, request, obj, form, change): 
     obj.type=2 
     obj.save() 

Usando una señal también no es una solución ya que mi señal sender será el mismo Model, por lo que no puede detectar qué InlineModelAdmin enviarlo y lo que debe ser la type ...

¿Hay una manera que me permita configurar type campo antes de guardar?

Respuesta

23

La respuesta de Alasdair no es incorrecta, pero tiene algunos puntos dolorosos que podrían causar problemas. En primer lugar, al recorrer el formset utilizando form como el nombre de la variable, realmente anula el valor pasado al método para form. No es un gran problema, pero como puede guardar sin comprometerse directamente desde el formset, es mejor hacerlo de esa manera. En segundo lugar, el todo importante formset.save_m2m() se quedó fuera de la respuesta. Los Django docs actuales recomiendan lo siguiente:

def save_formset(self, request, form, formset, change): 
    instances = formset.save(commit=False) 
    for instance in instances: 
     # Do something with `instance` 
     instance.save() 
    formset.save_m2m() 

El problema se va a ejecutar en es que el método save_formset debe continuar el padre ModelAdmin en lugar de los inline, y desde allí, no hay manera de saber qué línea en realidad está siendo utilizado. Si tiene un obj con dos "tipos" y todos los campos son iguales, entonces debe usar modelos de proxy y puede anular el método de guardar de cada uno para establecer automáticamente el tipo apropiado.

class CustomerCompanyType1(CustomerCompany): 
    class Meta: 
     proxy = True 

    def save(self, *args, **kwargs): 
     self.type = 1 
     super(CustomerCompanyType1, self).save(*args, **kwargs) 

class CustomerCompanyType2(CustomerCompany): 
    class Meta: 
     proxy = True 

    def save(self, *args, **kwargs): 
     self.type = 2 
     super(CustomerCompanyType2, self).save(*args, **kwargs) 

Entonces, no necesita hacer nada especial con sus líneas. Simplemente cambie sus clases de administrador en línea existentes para usar su modelo de proxy apropiado, y todo se resolverá solo.

+0

+1 buen enfoque para usar modelos de proxy.Actualicé mi respuesta para corregir los errores más obvios que mencionaste. Eso todavía deja el problema de resolver cuál inline representa el formset. – Alasdair

+0

En realidad, el enfoque del modelo de proxy elimina la necesidad de anular 'save_formset'. Los proxies mismos han anulado los métodos 'save' que saben cómo guardar como el tipo correcto. Entonces, simplemente usa las líneas sin preocuparse por eso. –

+0

Mi comentario no estaba claro: estaba de acuerdo en que, incluso después de solucionar los problemas en 'save_formset' (' save_m2m', etc.), todavía estaba el problema de qué en línea estaba guardando. Entendí que el enfoque del modelo de proxy evita eso :) – Alasdair

5

Hay un método save_formset que puede anular. Tendría que calcular cuál en línea el formset representa de alguna manera.

def save_formset(self, request, form, formset, change): 
    instances = formset.save(commit=False) 
    for instance in instances: 
     # Do something with `instance` 
     instance.save() 
    formset.save_m2m() 
0

Otras respuestas son correctas cuando se trata de usar save_formset. Sin embargo, les falta una forma de verificar qué modelo está actualmente guardado. Para hacer eso, usted puede simplemente:

if formset.model == CustomerCompany: 
    # actions for specific model 

lo que haría que el aspecto función save_formset como: (suponiendo que lo que desea es anular salvo por el modelo (s) específica)

def save_formset(self, request, form, formset, change): 

    # if it's not the model we want to change 
    # just call the default function 
    if formset.model != CustomerCompany: 
     return super(CustomerAdmin, self).save_formset(request, form, formset, change) 

    # if it is, do our custom stuff 
    instances = formset.save(commit=False) 
    for instance in instances: 
     instance.type = 2 
     instance.save() 
    formset.save_m2m() 
Cuestiones relacionadas