Почему мы вызываем super().get_queryset() в методе get_queryset в Django?

У меня есть метод в моем проекте Django:

определение get_queryset(self): набор запросов = super(OrderListView, self).get_queryset() возвращает набор запросов.фильтр(инициатор=self.request.user) Я не понимаю, почему мы используем queryset = super(OrderListView, self).get_queryset() внутри get_queryset.

Какова цель этой строки? Что именно она делает? Почему мы вызываем super() здесь? Почему мы вызываем один и тот же метод (get_queryset) внутри него самого? Я пытался разобраться в этом, но объяснения пока не прояснили мне ситуацию. Я был бы признателен за простой и удовлетворяющий меня ответ.

Прежде чем вы сможете вернуть отфильтрованный набор запросов, у вас должен быть набор запросов, который можно фильтровать. Итак, первая строка извлекает набор запросов каким-либо образом, определенным в суперклассе. Затем вторая строка возвращает его отфильтрованную версию.

def get_queryset(self):
    # 1. Get the original queryset
    queryset = super(OrderListView, self).get_queryset()

    # 2. Filter the queryset
    return queryset.filter(initiator=self.request.user)

Для этого есть несколько причин.

Прежде всего, ListView можно создать QuerySet двумя способами: указав атрибут .model или атрибут .queryset. Таким образом, если бы вы использовали self.queryset, это не сработало бы для ListView, где вы используете .model подход, подобный:

from django.views.generic import ListView


class MyListView(ListView):
    model = MyModel

    #    🖟 will ***not*** work
    def get_queryset(self):
        return self.queryset.filter(initiator=self.request.user)

Во-вторых, .get_queryset() из MultipleObjectMixin, который является комбинацией, которая дает ListView метод .get_queryset(), также упорядочивает набор запросов, если .ordering определено, или .get_ordering() возвращает что-то отличное от None.

Вы также можете задать свои собственные миксины, например, с помощью:

class ActiveItemsMixin:
    def get_queryset(self):
        return super().get_queryset().filter(active=True)

и смешайте его в виде:

class MyListView(ActiveItemsMixin, ListView):
    # …

Тогда super().get_queryset(), таким образом, вернет элементы, у которых есть active=True, и, таким образом, вы можете "связать" операции фильтрации и, таким образом, определить полезные миксины.

<время работы/>

Примечание: С тех пор как PEP-3135 [pep], вам не нужно вызывать super(…) с параметрами, если первым параметром является класс, в котором вы определяете метод, а вторым - первый параметр (обычно self) функции.

Я думаю, вам нужно понять основы объектно-ориентированного программирования и концепцию переопределения.

По сути, когда вы наследуете от родительского/базового класса, вы наследуете все свойства и методы этого класса, которые теперь доступны в вашем дочернем классе.

Могут быть случаи, когда вам нужно переопределить метод, но вы все равно хотите сохранить части реализаций метода из родительского класса. Помните о DRY - Не повторяйтесь, в этом случае вам не нужно изобретать велосипед или реализовывать эти функции заново, вы можете просто вызвать super().method_name(), чтобы сделать эти реализации доступными в методе вашего дочернего класса, и изменить его. в противном случае функции метода из родительского класса будут недоступны.

Я приведу вам пример ниже. Рассмотрим следующие классы фигур и квадратов.

Класс Square наследуется от Shape и переопределяет область, а также описывает методы, обеспечивающие более конкретную реализацию квадрата. Однако он по-прежнему вызывает super().area() и super().describe() для повторного использования логики родительского класса, а затем добавляет дополнительное поведение.

class Shape:
    def __init__(self, length, width):
        self.length = length
        self.width = width

    def area(self):
        # Default implementation for a generic shape
        return self.length * self.width

    def describe(self):
        return f"This is a shape with side length {self.length} and side width {self.width}."


class Square(Shape):
    def __init__(self, side_length):
        super().__init__(side_length, side_length)  # Initialize the parent class

    def area(self):
        # Call the parent class's area() method
        parent_area = super().area()
        print(f"Parent class area: {parent_area}")

        # Add specific logic for a square
        square_area = self.side_length ** 2
        print(f"Square area: {square_area}")
        return square_area

    def describe(self):
        # Extend the parent class's describe() method
        parent_description = super().describe()
        return f"{parent_description} Specifically, this is a square."

*** ТЕСТИРОВАНИЕ ***


# Create a Square object
square = Square(5)  



# Call the overridden area() method
print("Area of the square:", square.area()) 

# outputs => Parent class area: 25

# outputs => Area of the square: 25

# Call the overridden describe() method
print(square.describe())  

# outputs => This is a shape with side length 5 and side width 5. Specifically, this is a square.

Как вы можете видеть в выходных данных области для квадратного объекта, мы переопределили площадь и описать методы, но мы вызываем super().area() и super().describe(), чтобы сделать доступными свойства родительских методов и внести в них изменения.

Теперь в вашем случае в Django, где вы должны вызвать queryset = super(OrderListView, self).get_queryset().

Он отвечает за вызов родительской функции get_queryset(), которая имеет несколько реализаций, одна из которых отвечает за выборку объектов из базы данных. Это, конечно, абстрагировано.

Очевидно, что вы выполняете фильтрацию результатов по извлеченным объектам, и в качестве альтернативы вы могли бы написать логику для извлечения объектов с нуля, но это излишне, и вы, по сути, будете повторять логику.

Конечно, есть особые случаи, когда вам не нужны реализации методов из базового/родительского класса, и совершенно нормально не использовать super().

Помните, что одна из важных особенностей наследования классов и методов заключается в том, что, по сути, вы можете писать поддерживаемые и повторно используемые коды, в то время как вы сосредотачиваете свое внимание на другой логике.

Вернуться на верх