Как получить различные наборы запросов в шаблонах 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 %}