Как получить различные наборы запросов в шаблонах Django из представлений Django

В моем приложении для блога я хочу позволить неизвестным пользователям видеть статьи, но я также хочу позволить зарегистрированным пользователям видеть на той же странице (в другом месте) их собственные статьи; что-то вроде:

Ваши статьи: список (только если пользователь вошел в систему)

ВСЕ СТАТЬИ: список

Обратите внимание, что мне нужно показывать статьи в зависимости от того, какой пользователь вошел в систему, поэтому url должен быть таким:

path('<int:user_id>/', views.IndexView.as_view(), name='index'),

index.html:

{% if user.is_authenticated %}
   Your articles:
   <div class="container py-5">
        {% if article_list %}
            {% for article in article_list %}
                <div class="container">
                    <div class="row">
                        <div class="col">
                            {{article.author}}
                        </div>
                        <div class="col">
                            {{article.title}}
                        </div>
                        <div class="col">
                            {{article.pub_date}}
                        </div>
                        <a href=" {% url 'blog_app:detail' user_id = user.id %} ">
                            <div class="col">
                                Open article
                            </div>
                        </a>
                    </div>
                </div>
            {% endfor %}
        {% else %}
                <b>No articles!</b>
        {% endif %}
    </div>
{% endif %}

views.py:

class IndexView(ListView):
    model = Article
    template_name = 'blog_app/index.html'
    context_object_name = 'article_list'

    #return articles of a particular author
    def get_queryset(self):
        self.article = get_object_or_404(Article, author_id=self.kwargs['user_id'])
        return Article.objects.filter(
            author = self.article.author
        )

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

Бонусный вопрос:

Могу ли я разрешить неизвестным пользователям заходить на страницу статей, если в url необходимо указать id пользователя?

Вам необходимо указать:

def get_context_data(self, **kwargs):
    context = super().get_context_data(**kwargs)
    context['all_articles'] = Article.objects.all()
    return context

Тогда вы также можете использовать оператор if в шаблоне, чтобы проверить, существует ли {{all_articles}}.

"Могу ли я разрешить неизвестным пользователям заходить на страницу статей, если в url нужно указать id пользователя?"

У неавторизованных пользователей нет ID, это приведет к ошибке. Если вы хотите, чтобы пользователи переходили к автору текущей просматриваемой статьи, не будет ли это {{article.author.id}}? (Не уверен, что это то, что вы хотите)

Просто используйте стандартный контекст. Добавьте этот метод к вашему представлению (изменив имена, очевидно):

def get_context_data(self, **kwargs):
    context = super().get_context_data(**kwargs)
    context['book_list'] = Book.objects.all()
    return context

Бонусный ответ:

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

http://example.com/1/

Но если кто-то не авторизован, эта ссылка: <a href=" {% url 'blog_app:detail' user_id = user.id %} "> вызовет ошибку, но, конечно, из-за {% if user.is_authenticated %} она все равно не будет отображена.

Вам необходимо установить правильные разрешения для вашего представления.

Я думаю, что вы также можете переопределить метод get_queryset() в соответствии с различными условиями, так:

class IndexView(ListView):
    model = Article
    template_name = 'blog_app/index.html'
    context_object_name = 'article_list'

    
    def get_queryset(self):
        qs=super().get_queryset()
        if self.request.user.is_authenticated:
            article=get_object_or_404(Article,author_id=self.kwargs['user_id'])
            return qs.filter(author=article.author) #filtered queryset
        else:
            return qs #default queryset

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

class IndexView(ListView):
    model = Article
    template_name = 'blog_app/index.html'
  
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['all_article_list'] = Article.objects.all()
        context['author_article_list'] = Article.objects.filter(
            pub_date__year = self.kwargs['year'],
            pub_date__month = self.kwargs['month'],
            author = self.kwargs['user_id']
        ).order_by('-pub_date')
        return context

В шаблонах django я использовал эти контекстные имена для итера статей:

Author articles:
{% if user.is_authenticated %}
   {% if author_article_list %}
            {% for article in author_article_list %}
             ...
            {% endfor %}
   {% endif %}
{% endif %}

All articles:
{% if all_article_list %}
            {% for article in all_article_list %}
             ...
            {% endfor %}
{% endif %}
Вернуться на верх