Hi all. I tried googling. Did not help. I hope you can.
I have a small project with an Article model. It has article.title and article.body.
I have tried making a url pattern for catching “A/” and making it go to a template that only shows all the objects, that begins with the letter a
I can’t figure out how to capture the A in the url and send it to my ListView (which will be filtered).
I tried filtering in both the view and the template.
I can get it working by hardcoding the “A” in my view, but I would like it to read my url and pass the first letter instead. Please help
Some of my code:
views.py
class ArticleListViewByLetter(LoginRequiredMixin, ListView):
model = Article
template_name = "article_list_filter.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["letter"] = "A"
return context
This is to test if I have access to the variable: {{ letter }} (note: I do. It writes A)
{% for article in article_list %}
{% if article.title|first == letter %}
[Edit: I see you almost got it. If you’re going to create the complete queryset within your method, there’s no need to call super - you’re discarding the return from the function, so there’s no need to call it.]
Probably the easiest thing to do is to throw a couple of print statements into get_queryset to see what’s happening with the query. (I’d print both self.kwargs[‘letter’] and queryset)
Ok, since you’ve already limited your queryset to the articles you’re interested in, now you need to remove the if from your template (along with the corresponding endif).
Before I can answer this appropriately, how familiar or comfortable are you with the Django generic Class-Based Views?
You’re obviously familiar enough to use them effectively - otherwise you wouldn’t have gotten to this point. So that leaves me a little unsure as to how I need to target my answer.
The quick answer is that the fundamental purpose of get_queryset in a ListView is to create the queryset being used to build the list to be rendered. The get_context_data is available to add other data to the context being rendered by the template.
Yes, you can create the queryset-to-be-rendered-in-the-list in get_context_data, but then your CBV is doing double work. The get_queryset method will still get called, and the base queryset will be created before being overwritten by the queryset created in get_context_data.
I’ll also refer you to two third-party sites that I found have helped my understanding tremendously -
Now I went back and fiddled some more. And something is still a little off. I will post my code below. But just to recap I’m trying to catch a urlpattern like “Articles/A” and it will go to a generic ListView page and show all the articles that starts with A.
I’m hoping to save the A to the context under the key “letter” vis str:letter in the urls.py url pattern and to test if it comes through - can be shown on the page in the template.
I am getting all the right articles from the dtb, but the variable wont show.
Snips from my code:
from the template file:
{% block title %}Articles{% endblock title %}
{% block content %}
This is to test if I have access to the variable: {{ letter }}
{% if letter %}
{{ letter }}
{% endif %}
<br>
This is to demonstrate get_context_data in the view. The time is now: {{ now }}
<br>
{% for article in article_list %}
<!-- Articles show up here - which works on my page-->
my line from urls.py (which I think is where I dont fully understand how to pass the string correctly):
You still need to pass the letter through the context to the template to be rendered. You’re adding “now” to the context, you also need to add “letter”.
That passes it from the url to the view. Now the view needs to provide it to the rendering engine to make it available to the template - that’s the purpose of the context.
Since I am still practicing and I get som much good help in here I will share this too.
I was thinking about class based vs. function based and I tried (and somewhat succeeded) in writing both.
Comments are welcome. (I refer back to my own posts and your answers here as my personale stack-overflow Function-based:
I’m also learing Django, in my little experience at this stage I’m almost always use function based view as there is less ‘magic’ in it. I do write more code but what’s happening in the view is more ‘explicit’.
I guess that with experience I will switch to Class based view as they are certainly more rapid to write.