How to iterate queryset dictionary in django template - django

This is my dictionary i get from view:
{'questions_in_topic': <QuerySet [{'question_id__description': 'Describe your most significant leadership experience'}, {'questi
on_id__description': 'Which kind of leader are you?'}]>}
How do I show individual questions in django template?
The view is below:
def get_question_from_topic(request):
if request.method == "GET":
questions_in_topic = QuestionTopic.objects.filter(topic_id=request.GET['topicId']).values('question_id__description').order_by('question_id__description')
print(questions_in_topic)
context = { 'questions_in_topic': questions_in_topic }
print(context)
return render(request, 'recruiter/add_question_library.html', context)
return render(request, 'recruiter/add_question_library.html', context)

{% if questions_in_topic %}
{% for question in questions_in_topic %}
Question: {{ question }}
{% endfor %}
{% endif %}

If you're only accessing one field from the queryset then using values_list is probably better for your needs
Changing
questions_in_topic = QuestionTopic.objects.filter(topic_id=request.GET['topicId']).values('question_id__description').order_by('question_id__description')
To
questions_in_topic = QuestionTopic.objects.filter(topic_id=request.GET['topicId']).order_by('question_id__description').values_list('question_id__description', flat=True)
After this questions_in_topic will be a list of strings. You can then use these in your template like so
{% for question in questions_in_topic %}
Question: {{ question }}
{% empty %}
There are no questions.
{% endfor %}

Related

multiple query model in same view django

I've been doing some django these past weeks and I'm having a problem.
I have a page where Articles are shown. No problem while reovering all articles from db. But now I'd like to get all categories (an Article has a category) that I have in my database.
So I can display like this in my page:
List of categories
-cat1
-cat2
-cat3
List of articles
-art1
-art2
-art3
But I don't know how to do with both queries.
Here's what I've tried.
class IndexView(generic.ListView):
template_name = 'eduardoApp/index.html'
context_object_name = 'article_list'
def get_queryset(self):
return Article.objects.order_by('article_name')
def get_categories(request):
category_list=Category.objects.all()
context = {'category_list':category_list}
return render(request,'eduardoApp/index.html',context)
And in my view:
<h2>List of categories</h2>
{% if category_list %}
{% for category in category_list %}
<p>{{ category.name }}</p>
{% endfor %}
{% else %}
<p>no categorys</p>
{% endif %}
<h2>List of articles</h2>
{% if article_list %}
<div class="flex-container">
{% for article in article_list %}
<div>{{ article.article_name }}</div>
{% endfor %}
</div>
{% else %}
<p>No articles...</p>
{% endif %}
{% endblock %}
In my view I keep seeing no categorys displayed (since category_list does not exist but don't know why and how to fix)
ListView is creating context with 'objects' as queryset get_queryset returns.
I suppose your custom method get_categories hasn't been used anywhere?
Best practice here is to override get_context_data method like...
class IndexView(generic.ListView):
...
def get_context_data(self, **kwargs):
context = super(IndexView, self).get_context_data(**kwargs)
context['category_list'] = ...
return context

How to Create a UpdateForm with TemplateView?

I need to create a UpdateForm with a TemplateView. Why with TemplateView? Because, I has a attribute what is geo_location, and I'm using LeafLet maps, and LeafLet maps doesn't work with generic.UpdateView or others the same type.
Here my views from Update:
class UpdateStore(LoginRequiredMixin, TemplateView):
template_name = 'store_form'
success_url = reverse_lazy('register:store_list')
def post(self, request, *args, **kwargs):
store_id = kwargs['store']
store = get_object_or_404(Store, pk=store_id)
form = StoreForm(request.POST, on_edit=True)
if form.is_valid():
form.save()
return redirect(reverse('register:store_list'))
else:
context = self.get_context_data()
context['data_form'] = form
return render(request, self.template_name, context)
return self.get(request)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
store_id = self.kwargs['store']
store = get_object_or_404(Store, pk=store_id)
data = {
'name': store.name,
'description': store.description,
'address': store.address,
'geo_loc': store.geo_loc,
'opened': store.opened
}
context['editing'] = True
context['data_form'] = StoreForm(initial=data, on_edit=True)
context['store'] = store
return context
Here is my template code:
{% extends 'base.html' %}
{% load bootstrap3 %}
{% load leaflet_tags %}
{% block extra_css %}
{% leaflet_css plugins="forms" %}
{% endblock %}
{% block body %}
<h1> Update Store </h1>
<form method="POST">
{% csrf_token %}
{{ form }}
{% buttons %}
<button type="submit">
{% bootstrap_icon "star" %} Save
</button>
{% endbuttons %}
</form>
{% endblock %}
{% block extra_js %}
{% leaflet_js plugins="forms" %}
{% endblock %}
I trying this, but in my template, the Forms doesn't load, and my template are blanked :(. Someone knows why? I need another method for get anything else?
Thanks.
The problem with your code is that you place the form in the data_form key of the context:
context['data_form'] = StoreForm(initial=data, on_edit=True)
and then on the template you try to use it with {{form}} instead of {{data_form}}. After that the form should be rendered.

Using redirect sends me to /tag/?search=input instead of /tag/input (Django URL argument from form)

I have a page where there is a path /tag/name_of_tag and you can see all posts tagged with that tag.
Inside the page, you can also select another tag in a form and go to that tag.
The problem is that instead of going to /tag/searched_tag, it goes to /tag/?search=searched_tag
How can I change it doesn't leave the ?search= part?
urls.py:
url(r'tag/(?P<input_tag>\w+)$', views.tag_view, name='tag'),
views.py:
def tag_view(request, input_tag):
form = TagSearchForm()
if request.method == 'GET':
form = TagSearchForm(request.GET)
if form.is_valid():
input = form.cleaned_data['search']
print(input)
return redirect('fortykwords:tag_view', input)
else:
form = SearchForm()
latest_post_list = Post.objects.filter(tags=input_tag, status__exact="published")
paginator = Paginator(latest_post_list, 3)
page = request.GET.get('page')
posts = paginator.get_page(page)
context = {'latest_post_list': latest_post_list, 'page_tag': input_tag, 'form': form}
return render(request, 'fortykwords/tag.html', context)
forms.py:
class TagSearchForm(forms.Form):
search = tagulous.forms.SingleTagField(
tag_options=tagulous.models.TagOptions(
autocomplete_view='fortykwords:post_tags_autocomplete'
),
label='Tags',
required=True,
help_text=_('Filter by lead tags. You can organize leads by any tag you want.'),
)
tag.html:
{% extends "base_generic.html" %}
{% block content %}
<form action="." method="get">
{{ form }}
<input type="submit" value="Submit" />
</form>
<h3>Posts with the tag {{ page_tag }}</h3>
{% if latest_post_list %}
<ul>
{% for post in latest_post_list %}
<li> {{ post.author }} {{ post.pub_date }}
<br>
{{ post.title }}</li>
{% for tag in post.tags.all %}
{{ tag.name }}
{% endfor %}
{% endfor %}
</ul>
{% else %}
<p>No posts are available.</p>
{% endif %}
{% endblock %}
You need to provide the argument input to redirect method as input_tag=input.
Example:
return redirect('fortykwords:tag_view', input_tag=input)
It's showing as /tag/?search=searched_tag because your form is submitting by GET but never getting to the redirect. It seems is_valid() is returning False.
I've tested a very similar version of your code and don't think it's a bug in tagulous, but would still be interested to know what had gone wrong (I wrote tagulous). Spotted a couple of places you can streamline your code a bit, so try::
def tag_view(request, input_tag):
# Can't see any POSTs in your example, so you can pass the form GET here
# Might also be nice to pass the original tag in so it shows in the form
form = TagSearchForm(request.GET, initial={'search': input_tag})
# The form already has the GET, so you can go straight into the is_valid
if form.is_valid():
input = form.cleaned_data['search']
print('Valid: ', input)
return redirect('fortykwords:tag_view', input)
else:
print('Invalid: ', form.errors, form.non_field_errors)
# You can remove the else for if not GET, which would never be reached
# on to pagination as before
(although fwiw I'd recommend ipdb instead of print)

Accessing Many-to-Many Values Django

article = get_object_or_404(Article,slug=slug)
categories = article.category.all()
Using render_to_response() , how can I use the categories in the view ?
Assuming you have the article in the template, you can do the following:
# In your view
return render_to_response('page.html', {'article': article})
# In your template
{% for category in article.category.all %}
{{ category.attribute }}
{% endfor %}
# Or, if you already have the categories
return render_to_response('page.html', {'categories': categories})
{% for category in categories %}
{{ category.attribute }}
{% endfor %}

Caught AttributeError while rendering: 'str' object has no attribute '_meta'

def broadcast_display_and_form(request):
if request.method == 'POST' :
form = PostForm(request.POST)
if form.is_valid():
post = form.cleaned_data['post']
obj = form.save(commit=False)
obj.person = request.user
obj.post = post
obj.save()
readers = User.objects.all()
for x in readers:
read_obj = BroadcastReader(person = x)
read_obj.post = obj
read_obj.save()
return HttpResponseRedirect('/broadcast')
else :
form = PostForm()
posts = BroadcastReader.objects.filter(person = request.user)
return render_to_response('broadcast/index.html', { 'form' : form , 'posts' : posts ,} )
My template
{% extends "base.html" %}
{% load comments %}
{% block content %}
<form action='.' method='POST'>
{{ form.as_p }}
<p>
<input type="submit" value ="send it" /></input>
</p>
</form>
{% get_comment_count for posts.post as comment_count %}
{% render_comment_list for posts.post %}
{% for x in posts %}
<p>
{{ x.post.person }} - {{ x.post.post }}
</p>
{% endfor %}
{% endblock %}
What is posts.post supposed to be? posts is a BroadcastReader QuerySet, and probably doesn't have such an attribute? I'm guessing the comment rendering tags are causing your error? Try removing them, or using posts.0 or similar to debug.
Which "post" do you actually want to display comments for? Your view logic is unclear.