87

私のモデルの1つには、オブジェクトをグローバルに非表示にするために使用される削除済みフラグがあります。

class NondeletedManager(models.Manager):
    """Returns only objects which haven't been deleted"""

    def get_query_set(self):
        return super(NondeletedManager, self).get_query_set().exclude(deleted=True)

class Conversation(BaseModel):
    ...
    deleted = models.BooleanField(default=False)
    objects = NondeletedManager()
    all_conversations = models.Manager() # includes deleted conversations

削除された会話を含めるためにDjango管理モジュールによって使用されるデフォルトのクエリセットをオーバーライドするにはどうすればよいですか?

4

7 に答える 7

161

モデル管理者クラスのメソッドをオーバーライド できます。get_queryset

class MyModelAdmin(admin.ModelAdmin):
    def get_queryset(self, request):
        qs = super(MyModelAdmin, self).get_queryset(request)
        if request.user.is_superuser:
            return qs
        return qs.filter(author=request.user)

Django <= 1.5では、メソッドの名前は単に。であることに注意してくださいqueryset

于 2012-09-10T14:56:16.120 に答える
10

Konradは正しいですが、これはドキュメントに示されている例よりも困難です。

削除された会話は、すでにそれらを除外しているクエリセットに含めることはできません。したがって、admin.ModelAdmin.querysetを完全に再実装する以外のオプションは表示されません。

class ConversationAdmin (admin.ModelAdmin):

    def queryset (self, request):
        qs = Conversation.all_conversations
        ordering = self.get_ordering(request)
        if ordering:
            qs = qs.order_by(*ordering)
        return qs
于 2012-09-10T15:26:00.337 に答える
4

次の場合、何が問題になりますか。

class Conversation(BaseModel):
    ...
    deleted = models.BooleanField(default=False)
    objects = models.Manager() # includes deleted conversations
    nondeleted_conversations = NondeletedManager()

したがって、独自のアプリ/プロジェクトではConversation.nondeleted_conversations()、組み込みの管理アプリを使用して、それを実行させます。

于 2012-09-10T14:51:01.640 に答える
3

これは、Djangoプロキシモデルを使用して行うことができます。

# models.py
class UnfilteredConversation(Conversation):
    class Meta:
        proxy = True

    # this will be the 'default manager' used in the Admin, and elsewhere
    objects = models.Manager() 

# admin.py
@admin.register(UnfilteredConversation)
class UnfilteredConversationAdmin(Conversation):
    # regular ModelAdmin stuff here
    ...

または、既存のModelAdminクラスがある場合は、次のように再利用します。

admin.site.register(UnfilteredConversation, ConversationAdmin)

このアプローチは、元の会話モデルでデフォルトマネージャーをオーバーライドすることで発生する可能性のある問題を回避します。これは、デフォルトマネージャーがManyToMany関係および逆ForeignKey関係でも使用されるためです。

于 2019-02-01T00:36:17.593 に答える
2

受け入れられたソリューションは私にとってはうまく機能しますが、もう少し柔軟性が必要だったので、変更リストビューを拡張して、カスタムクエリセットパラメーターを追加することになりました。これで、デフォルトのクエリセット/フィルターをそのように構成できますが、別のフィルター(パラメーターの取得)を使用して変更することもできます。

def changelist_view(self, request, extra_context=None):
    if len(request.GET) == 0 :
        q = request.GET.copy()
        q['status__gt'] = 4
        request.GET = q
        request.META['QUERY_STRING'] = request.GET.urlencode()

    return super(WorksheetAdmin,self).changelist_view(request, extra_context=extra_context)
于 2014-09-04T00:34:10.020 に答える
2

Natan Yellinは正しいですが、マネージャーの順序を変更できます。最初の順序がデフォルトになり、次に管理者が使用します。

class Conversation(BaseModel):
    ...
    deleted = models.BooleanField(default=False)

    all_conversations = models.Manager() # includes deleted conversations
    objects = NondeletedManager()

次のように、代わりにget_queryset()使用の管理者実装._default_manager.objects

qs = self.model._default_manager.get_queryset()

ref DjangogithubBaseModelAdminの実装

これにより、YourModel.objectsを使用するたびに、削除されたオブジェクトが含まれないようになりますが、ジェネリックビューなどでは._default_managerも使用されます。次に、オーバーライドしない場合、get_querysetは解決策ではありません。ListViewと管理者を確認しました。

于 2019-05-30T20:50:11.937 に答える
0

これらの答えのいくつかを、私が最も簡潔で有用だと思ったもので拡張すること。

エントリを表示するための「名前」のようなフィールドがあると仮定しました。

# admin.py

from django.contrib import admin

@admin.register(Conversation)
class ConversationAdmin(admin.ModelAdmin):
    list_display = ('name', '_is_deleted')


    # Nice to have but indicates that an object is deleted
    @admin.display(
        boolean=True,
        ordering='deleted'
    )
    def _is_deleted(self, obj):
        return obj.deleted

    def get_queryset(self, request):
        return Conversation.all_conversations

これにより、次のようなインターフェイスが提供されます。

フラグが削除されたDjango管理者リスト

モデルのサブクラス化で私が見つけた問題は、メタ継承とリバースパスルックアップで問題が発生することでした。

于 2021-09-01T10:54:08.497 に答える