Подтвердить что ты не робот

Переопределить запрос по умолчанию в Django admin

Одна из моих моделей имеет удаленный флаг, который используется для скрытия объектов по всему миру:

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, для включения удаленных цепочек?

4b9b3361

Ответ 1

Вы можете переопределить метод 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.

Ответ 2

Конрад прав, но это сложнее, чем пример, приведенный в документации.

Удаленные разговоры не могут быть включены в набор запросов, который уже исключает их. Поэтому я не вижу другого варианта, кроме повторной реализации 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

Ответ 3

Что было бы неправильно со следующим:

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

Итак, в ваших собственных приложениях/проектах вы используете Conversation.nondeleted_conversations() и позволяете встроенному приложению администратора делать это.

Ответ 4

Принятое решение отлично работает для меня, но мне нужно было немного больше гибкости, поэтому я расширил представление списка изменений, чтобы добавить в пользовательский параметр набора запросов. Теперь я могу настроить свой набор/фильтр по умолчанию как таковой, и его можно изменить с помощью другого фильтра (получить параметры):

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)

Ответ 5

Вы можете сделать это с моделью прокси 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.