2016-06-22 11 views
1

私はこの問題の解決策を見つけることなくかなりの時間インターネットでコーミングしています。Django:新しいlinelineオブジェクトの親オブジェクトにアクセスする

私がやろうとしています何

...

私は次のモデルがあります:

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) 

今すぐメインモデルが追跡しているので、トラッキングのための私の管理者は、次のようになります。

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

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

これは現在の設定に適用されます。

は今私の探求:私は新しいTrackingEventのインラインを追加するときTrackingAdminで

は、私が追跡の最後TrackingEventに従うことが許されているものを、onlyeするTrackingEventTypeの選択肢を制限したいです。 (Tracking.last_event == TrackingEventType.required_previous_event)。

このため、InlineTrackingEventの関連するTrackingにアクセスしてlast_eventにアクセスし、それに応じてTrackingEventTypeのオプションをフィルタリングする必要があります。

は、だから私は、この発見: Accessing parent model instance from modelform of admin inlineを、私はそれに応じTrackingEventInline設定するとき:

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 

を私は誰もがこの問題を解決する方法を知っていKeyError at /admin/.../tracking/2/change/ 'parent_object'self.parent_object = kwargs.pop('parent_object')


から入手しますか?私は間違った方法で問題に近づいていますか?私はこれはフロントエンドのカスタムフォームではかなり簡単だと思いますが、アプリケーション全体が管理者から使用されるようになっているので、実際には管理者を使用したいと思います。カスタムを構築するには大変な作業になりますこの問題のためだけに管理者インターフェイス:

+0

私はこれを見つけました:http://stackoverflow.com/questions/1883296/prepopulating-inlines-based-on-the-parent-model-in -the-django-admin とこれは:http://stackoverflow.com/questions/442040/pre-populate-an-inline-formsetここから私がそこに行くことができるところがわかります。 – platzhersh

答えて

0

[OK]をStackOverflowで投稿すると、問題をまっすぐにするのに役立ちます。私は私のために働く解決策をまとめることができました。

外部関数に独自のフォームを定義し、TrackingEvent用の2つのInlineAdminオブジェクトを定義します(1つは更新/編集用、1つは挿入用)。ここで

はコードです:私は、これは同じ問題で他の人に役立ちます願ってい

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) 

..私はこれを考え出す助けスタックオーバーフローのスレッドにいくつかのクレジット:

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

ご質問がある場合はお気軽にご質問ください

関連する問題