2009-08-07 12 views
4

モデル内の情報が追加または変更されているかどうかを検出する方法がある場合。Django admin:変更フォームのフィールドのみを除外

フィールドを除外するには、この情報を使用できます。

私が話していることを説明する擬似コード。

class SubSectionAdmin(admin.ModelAdmin): 
    if something.change_or_add = 'change': 
     exclude = ('field',) 
    ... 

おかげ

答えて

5
class SubSectionAdmin(admin.ModelAdmin): 
    # ... 
    def change_view(self, request, object_id, extra_context=None):  
     self.exclude = ('field',) 
     return super(SubSectionAdmin, self).change_view(request, object_id, extra_context) 
+0

self.exclude =( 'field'、) – falko

+0

フィールドが管理フォームのカスタムフィールドの場合はどうなりますか? –

+1

これがなぜ危険で、行く方法でないのかについては、以下の回答を参照してください。管理オブジェクトはシングルトンなので、self.excludeを設定すると、後続のadd_view呼び出しのためにSubSectionAdminの状態が変更されます。 – aggieNick02

10

オーウェルの答えは全体SubSectionAdminシングルトンは、その除外プロパティを変更いたします。ただ、これらの余分なフィールドを除外するためのフォームを通知します

class SubSectionAdmin(admin.ModelAdmin): 
    # ... 
    def get_form(self, request, obj=None, **kwargs): 
     """Override the get_form and extend the 'exclude' keyword arg""" 
     if obj: 
      kwargs.update({ 
       'exclude': getattr(kwargs, 'exclude', tuple()) + ('field',), 
      }) 
     return super(SubSectionAdmin, self).get_form(request, obj, **kwargs) 

フィールドはリクエストごとに除外されていることを確認するための方法のような何かを行うことです。

これは除外されている必須フィールドを与えられたどのように動作するかわからない...

+9

'kwargs.extend'の代わりに' kwargs.update'が必要です。 – Mitar

0

アプローチは、以下のオブジェクト広いexcludeプロパティをオーバーライドしないという利点があります。代わりに、それは要求

self.excludeを設定
class SubSectionAdmin(admin.ModelAdmin): 
    add_exclude = ('field1', 'field2') 
    edit_exclude = ('field2',) 

    def add_view(self, *args, **kwargs): 
     self.exclude = getattr(self, 'add_exclude',()) 
     return super(SubSectionAdmin, self).add_view(*args, **kwargs) 

    def change_view(self, *args, **kwargs): 
     self.exclude = getattr(self, 'edit_exclude',()) 
     return super(SubSectionAdmin, self).change_view(*args, **kwargs) 
+0

ModelAdminクラスはシングルトンなので、状態を変更することは問題があります – aggieNick02

4

の各タイプに基づいてリセットされているスティーブ・パイクが言及@として、全体SubSectionAdminシングルトンは、その除外プロパティを変更しますありません。 シングルトンは、クラスがインスタンス化されるたびに同じインスタンスを再利用するクラスです。したがって、インスタンスはコンストラクタの最初の使用時にのみ作成され、後でコンストラクタを使用すると同じインスタンスが返されます。より詳しい説明はwiki pageを参照してください。 これは、変更時にフィールドを除外するコードを記述すると、アイテムを最初に追加した場合はそのフィールドが存在しますが、変更のためにアイテムを開くと、フィールドは次の追加ページへの訪問。

要求ごとの挙動を達成するための最も簡単な方法は、我々は、オブジェクトを変更している場合、我々は、オブジェクト、およびオブジェクトのインスタンスを追加する場合Noneあるobj引数、上get_fieldsおよびテストを使用することです。 get_fieldsメソッドは、Django 1.7から入手できます。

class SubSectionAdmin(admin.ModelAdmin): 
    def get_fields(self, request, obj=None): 
     fields = super(SubSectionAdmin, self).get_fields(request, obj) 
     if obj: # obj will be None on the add page, and something on change pages 
      fields.remove('field') 
     return fields 

更新:

あなたは要素を削除するには、リストにfieldsを変換する必要があるかもしれないのでget_fieldsは、タプルを返すことがありますのでご注意ください。 削除しようとしているフィールド名がリストにない場合は、エラーが発生することもあります。したがって、それは、あなたがフィールドを除外し、他の要因を持っているいくつかのケースでは、除外のセットを構築し、リストの内包表記を使用して削除する方が良い場合があります。

また
class SubSectionAdmin(admin.ModelAdmin): 
    def get_fields(self, request, obj=None): 
     fields = list(super(SubSectionAdmin, self).get_fields(request, obj)) 
     exclude_set = set() 
     if obj: # obj will be None on the add page, and something on change pages 
      exclude_set.add('field') 
     return [f for f in fields if f not in exclude_set] 

あなたはまた、結果のdeepcopyを作ることができますget_fieldsetsメソッドです。これは、他の使用例では、物を排除するためのより良いコンテキストへのアクセスを提供する可能性があります。フィールドセット名を操作する必要がある場合は、これが最も便利です。またフィールドセットを実際に使用する場合は、get_fieldsの呼び出しを省略するため、これは唯一の方法です。

from copy import deepcopy 

class SubSectionAdmin(admin.ModelAdmin): 
    def get_fieldsets(self, request, obj=None): 
     """Custom override to exclude fields""" 
     fieldsets = deepcopy(super(SubSectionAdmin, self).get_fieldsets(request, obj)) 

     # Append excludes here instead of using self.exclude. 
     # When fieldsets are defined for the user admin, so self.exclude is ignored. 
     exclude =() 

     if not request.user.is_superuser: 
      exclude += ('accepted_error_margin_alert', 'accepted_error_margin_warning') 

     # Iterate fieldsets 
     for fieldset in fieldsets: 
      fieldset_fields = fieldset[1]['fields'] 

      # Remove excluded fields from the fieldset 
      for exclude_field in exclude: 
       if exclude_field in fieldset_fields: 
        fieldset_fields = tuple(field for field in fieldset_fields if field != exclude_field) # Filter 
        fieldset[1]['fields'] = fieldset_fields # Store new tuple 

     return fieldsets 
関連する問題