2016-06-22 2 views
1

Ich kämme seit einiger Zeit durch das Internet, ohne eine Lösung für dieses Problem zu finden.Django: Zugreifen auf das übergeordnete Objekt in einem neuen linline-Objekt

Was ich zu tun versuchen ...

Ich habe die folgenden Modelle:

class TrackingEventType(models.Model): 
    required_previous_event = models.ForeignKey(TrackingEventType) 

class TrackingEvent(models.Model): 
    tracking = models.ForeignKey(Tracking) 

class Tracking(models.Model): 
    last_event = models.ForeignKey(TrackingEvent) 

Nun ist das wichtigste Modell verfolgt, so dass mein Admin für Tracking-wie folgt aussieht:

class TrackingEventInline(admin.TabularInline): 
    model = TrackingEvent 
    extra = 0 

class TrackingAdmin(admin.ModelAdmin): 
    inlines = [TrackingEventInline] 

Das war es für das aktuelle Setup.

Jetzt meine Suche:

Im TrackingAdmin, wenn ich neue TrackingEvent inlines hinzufügen möchte ich die Möglichkeiten von TrackingEventType begrenzen diejenigen onlye, die auf dem letzten TrackingEvent der Verfolgung sind erlaubt zu folgen. (Tracking.last_event == TrackingEventType.required_previous_event).

Dazu müsste ich in der Lage sein, auf das InlineTrackingEvent-Tracking zuzugreifen, um auf das last_event zuzugreifen und die Optionen für TrackingEventType entsprechend zu filtern.

So fand ich dies: Accessing parent model instance from modelform of admin inline, aber wenn ich TrackingEventInline entsprechend eingerichtet:

class MyFormSet(forms.BaseInlineFormSet): 
    def _construct_form(self, i, **kwargs): 
     kwargs['parent_object'] = self.instance 
     print self.instance 
     return super(MyFormSet, self)._construct_form(i, **kwargs) 


class MyForm(forms.ModelForm): 
    def __init__(self, *args, **kwargs): 
     print kwargs 
     self.parent_object = kwargs.pop('parent_object') 
     super(MyForm, self).__init__(*args, **kwargs) 

class TrackingEventInline(admin.TabularInline): 
    form = MyForm 
    formset = MyFormSet 

    model = TrackingEvent 
    extra = 0 

ich ein KeyError at /admin/.../tracking/2/change/ 'parent_object' von self.parent_object = kwargs.pop('parent_object')


Kennt jemand bekommen, wie dieses Problem zu lösen? Gehe ich das Problem falsch an? Ich denke, das wäre ziemlich einfach in einer benutzerdefinierten Form im Frontend, aber ich möchte wirklich den Admin verwenden, weil die ganze Anwendung so aufgebaut ist, dass sie vom Admin benutzt wird, und es wäre verdammt viel Arbeit, einen Custom zu erstellen Admin-Schnittstelle nur wegen dieses Problems :)

+0

Ok, also habe ich das gefunden: http://StackOverflow.com/Questions/1883296/prepopulating-inlines-based-on-the-parent-model-in -the-django-admin und das: http://stackoverflow.com/questions/442040/pre-populate-an-inline-formset und werde sehen, wo ich von dort gehen kann .. – platzhersh

Antwort

0

Ok, so Beitrag auf StackOverflow hilft immer, um das Problem gerade zu bekommen. Ich konnte eine Lösung zusammenstellen, die für mich funktioniert.

Es umfasst die Definition meiner eigenen Form in einer äußeren Funktion, sowie die Definition von zwei InlineAdmin-Objekten für TrackingEvent (eine für Update/Edit, eine nur für Einfügen).

Hier ist der Code:

def create_trackingevent_form(tracking): 
    """ 
    """ 
    class TrackingEventForm(forms.ModelForm): 
     """ 
     Form for Tracking Event Inline 
     """ 

     def clean(self): 
      """ 
      May not be needed anymore, since event type choices are limited when creating new event. 
      """ 
      next_eventtype = self.cleaned_data['event_type'] 
      tracking = self.cleaned_data['tracking'] 
      # get last event, this also ensures last_event gets updated everytime the change form for TrackingEvent is loaded 
      last_eventtype = tracking.set_last_event() 

      if last_eventtype: 
       last_eventtype = last_eventtype.event_type 

      pk = self.instance.pk 
      insert = pk == None 
      # check if the event is updated or newly created 
      if insert: 
       if next_eventtype.required_previous_event == last_eventtype: 
        pass 
       else: 
        raise forms.ValidationError('"{}" requires "{}" as last event, "{}" found. Possible next events: {}'.format(
         next_eventtype, 
         next_eventtype.required_previous_event, 
         last_eventtype, 
         '"%s" ' % ', '.join(map(str, [x.name for x in tracking.next_tracking_eventtype_options()])) 
         ) 
        ) 
      else: 
       pass 
      return self.cleaned_data 

     def __init__(self, *args, **kwargs): 
      # You can use the outer function's 'tracking' here 
      self.parent_object = tracking 

      super(TrackingEventForm, self).__init__(*args, **kwargs) 
      self.fields['event_type'].queryset = tracking.next_tracking_eventtype_options() 
      #self.fields['event_type'].limit_choices_to = tracking.next_tracking_eventtype_options() 

    return TrackingEventForm 


class TrackingEventInline(admin.TabularInline): 
    #form = MyForm 
    #formset = MyFormSet 

    model = TrackingEvent 
    extra = 0 

    #readonly_fields = ['datetime', 'event_type', 'note'] 

    def has_add_permission(self, request): 
     return False 



class AddTrackingEventInline(admin.TabularInline): 
    model = TrackingEvent 
    extra = 0 

    def has_change_permission(self, request, obj=None): 
     return False 

    def queryset(self, request): 
     return super(AddTrackingEventInline, self).queryset(request).none() 

    def get_formset(self, request, obj=None, **kwargs): 
     if obj: 
      self.form = create_trackingevent_form(obj) 
     return super(AddTrackingEventInline, self).get_formset(request, obj, **kwargs) 

Ich hoffe, das andere Menschen mit dem gleichen Problem hilft .. Einige Kredit auf das Gewinde Stack-Überlauf, der mich mit diesem kommen geholfen:

Prepopulating inlines based on the parent model in the Django Admin

Limit foreign key choices in select in an inline form in admin

https://docs.djangoproject.com/en/1.9/ref/models/instances/#django.db.models.Model.clean_fields

Bitte zögern Sie nicht, Fragen zu stellen, wenn Sie irgendwelche haben

Verwandte Themen