Django 관리자의 기본 쿼리 세트 재정의


79

내 모델 중 하나에는 전체적으로 개체를 숨기는 데 사용되는 삭제 된 플래그가 있습니다.

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 관리 모듈에서 사용하는 기본 쿼리 셋을 어떻게 재정의 할 수 있습니까?


이러한 간단한 쿼리에 대해 사용자 지정 관리자가 정말로 필요합니까?
César

3
예, 삭제 된 개체는 일반적으로 무시되어야하므로 (관리 페이지 제외) 기본값을 설정하는 것이 좋습니다.
Natan Yellin

답변:


144

모델 관리자 클래스에서 메서드를 재정의 할 수 있습니다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.


3
이 경우 어떻게 작동합니까? ModelAdmin.queryset삭제 된 개체를 포함하도록에서 만든 쿼리 집합을 수정할 수 있습니까 ? 수퍼 클래스를 호출하는 대신 직접 쿼리 세트를 빌드하고 싶지 않습니다.
Natan Yellin

내 대답을보고 무슨 뜻인지 확인하십시오. 기능을 완전히 다시 구현하는 대안이 있습니까?
Natan Yellin

4
단순히 연결하는 것이 아니라 답변에 실제로 답을 넣는 것이 도움이됩니다. 그 링크는 이제 죽었으니 설명을하도록 업데이트하겠습니다.
Dan

16
장고 1.6에서 이 방법이 변경되었습니다get_queryset.
Fernando Macedo 2014

1
나는 이것을 작동시킬 수 없었다. .filter가 qs 객체에 없다는 오류가 발생합니다. 둘째, 요청 이외의 다른 용도로도 queryset을 사용할 수 없습니다. stackoverflow.com/questions/54472649/… 도움이 필요하십니까?
Gary

9

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

1
나는 그것에 아무런 문제가 없다고 생각합니다. 두 명의 관리자를 사용하는 것이 좋습니다. 그러나 Django 관리자가 주문 부분을 다시 구현할 필요가 없도록 후크를 제공 할 수 있다는 것은 사실입니다.
Thomas Orozco

3

다음과 같은 문제는 무엇입니까?

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

따라서 자신의 앱 / 프로젝트 Conversation.nondeleted_conversations()에서 기본 제공 관리자 앱 을 사용 하고이를 수행하도록합니다.


1
관리자 페이지를 제외한 모든 곳에서 삭제 된 개체를 무시하고 있으므로 이것이 기본값이어야한다고 생각합니다. 또한 이렇게하면 대화를 삭제하는 기능을 추가하여 레거시 코드를 업데이트 할 필요가 없습니다.
Natan Yellin

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)

2

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 관계에서도 사용되기 때문입니다.


1

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 Django github BaseModelAdmin 구현

이렇게하면 YourModel.objects를 사용할 때마다 삭제 된 개체가 포함되지 않지만 일반보기와 다른보기에서도 ._default_manager를 사용합니다. 그렇다면 get_queryset을 재정의하지 않으면 해결책이 아닙니다. ListView와 관리자를 확인했습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.