2013-02-13 32 views
9

Czy można zapisać powiązane obiekty przed faktycznym edytowanym obiektem w formularzu administratora django?Zapisz powiązane obiekty przed faktycznym edytowanym obiektem na django admin

Na przykład:

w models.py

class Parent(model.Model): 
    pass 

class Child(model.Model): 
    parent = models.ForeignKey(Parent) 

@receiver(post_save,sender = Parent) 
def notify_parent_save(sender, instance=None, **kwargs): 
    print "Parent save" 

@receiver(post_save,sender = Child) 
def notify_child_save(sender, instance=None, **kwargs): 
    print "Child saved" 

w admin.py

class ChildInline(admin.TabularInline): 
    model = Child 
    extra = 1 

class ParentsAdmin(admin.ModelAdmin): 
    inlines = [ChildInline] 

admin.site.register(Parent,ParentsAdmin) 

Teraz w Django administratora gdybym zapisać obiekt nadrzędny, to wyświetli na konsoli.

Parent save 
Child save 

muszę to się stało w revese kolejności:

Child save 
Parent save 

Odpowiedz

9

Poniższa uratuje dzieci pierwszy: odpowiedź

class ParentAdmin(admin.ModelAdmin): 
    inlines = [ChildInline] 

    def save_model(self, request, obj, form, change): 
     pass # don't actually save the parent instance 

    def save_formset(self, request, form, formset, change): 
     formset.save() # this will save the children 
     form.instance.save() # form.instance is the parent 
0

W zależności od tego, co dokładnie chcesz zrobić w swoim sygnałów, można po prostu zmienić post_save do pre_save dla modelu dziecka?

3

ccrisan przyniósł mi na dobrej drodze, ale myślę, że jest to wada dotycząca oszczędzania zachowania przypadkach, które jeszcze nie istnieją w bazie danych. W takim przypadku nie można najpierw zapisać powiązanych obiektów, ponieważ nie ma klucza obcego, na który mogą wskazywać. Dla mnie następujące rozszerzenie wystarczyły:

class ParentAdmin(admin.ModelAdmin): 
    inlines = [ChildInline] 

    def save_model(self, request, obj, form, change): 
     if not obj.pk: # call super method if object has no primary key 
      super(ParentAdmin, self).save_model(request, obj, form, change) 
     else: 
      pass # don't actually save the parent instance 

    def save_formset(self, request, form, formset, change): 
     formset.save() # this will save the children 
     form.instance.save() # form.instance is the parent 
5

miałem problemy z odpowiedziami w tym poście, więc zorientowali się bardziej zwięzłą odpowiedź. Wystąpił problem, ponieważ przy użyciu django-fsm, pozostałe odpowiedzi próbowałyby zapisać model wiele razy (raz dla każdego zestawu) zamiast raz na końcu.

def save_model(self, request, obj, form, change): 
    if not obj.pk: # call super method if object has no primary key 
     super(YourAdmin, self).save_model(request, obj, form, change) 
    else: 
     pass # don't actually save the parent instance 

def save_related(self, request, form, formsets, change): 
    form.save_m2m() 
    for formset in formsets: 
     self.save_formset(request, form, formset, change=change) 
    super(YourAdmin, self).save_model(request, form.instance, form, change) 

To niezbędne tylko odwraca kolejność save_model i save_related jak nazywa się w Django ModelAdmin source

+0

nie wiem, czy jest to wersja Django rzecz lub rzecz logiki biznesowej, ale dla Django 1.11 i mojego użytkowania. to wydaje się być właściwą odpowiedzią – ckot