Объясните запрос к базе

Есть модель:

class Follow(models.Model):
    user = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name="follower"
        )
    author = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name="following"
        )

И вью:

@login_required
def follow_index(request):
    post_list = Post.objects.filter(author__following__user=request.user)
    paginator = Paginator(post_list, 10)
    page_number = request.GET.get('page')
    page = paginator.get_page(page_number)
    return render(
        request, 'follow.html',
        {
            'page': page,
            'paginator': paginator
        })

Не понимаю этой строки:

Post.objects.filter(author__following__user=request.user)

  1. Дайте, пожалуйста, пошаговое объяснение того, что приходит в этой записи.
  2. Что означает __ в каждом случае это выражения.

Ответы (1 шт):

Автор решения: Roman Konoval

filter в простом случае принимает имя поля модели, т.е. Post.objects.filter(title='xx') будет искать посты, у которых атрибут title равен xx.

Поле модели может быть простого типа, например, string или int, а может быть тоже моделью, как в этом случае в модели Post есть поле author. И filter позволяет искать по полю ассоциированной модели. Например, Post.objects.filter(author__name='John Doe') находит посты, у которых у автора имя John Doe.

В общем случае может быть указана цепочка атрибутов. Начинается все с поля модели, к которой делаем запрос, и далее по цепочке. В примере из вопроса ищутся посты к которых автор связан через модель Follow с текущим пользователем из request.

Если объяснять "на пальцах", то это работает так: мы имеем связь между объектами (а точнее таблицами в БД). Post -> Author <-> Follow <-> User. Сначала ищется пользователь с заданным именем. Для него ищутся объекты в таблице Follow, которые на него ссылаются. Далее для всех найденных записей в Follow ищутся связанные с ними авторы. А далее все посты, которые связанны с найденными авторами.

На уровне БД и SQL делается join всех этих таблиц и фильтрация по идентификатору пользователя, который берется из request.user.

→ Ссылка