Django Need 2 values to unpack in for loop; got 1 - python

I have looked for other answers but cannot get this one working.
I have model Sitting with a field user_answers which stores a dictionary
{"437": "1574", "319": "hi", "383": "1428", "424": "1528", "203": "785"}
When I do
{% for key, value in sitting %}
<p> {{key}}--{{value}} </p>
<p> {{question.id}}--{{answer.id}} </p>
{% ifequal key question.id %}
{% ifequal value answer.id %}
<li class="list-group-item quiz-answers" >
<span><label for="id_answers_0"><input type="radio" name="answers_{{question.id}}" value="{{answer.id}}" style="margin-right:10px;" id="{{answer.id}}" selected required>
{{answer.content}} </label> </span></li>
{% else %}
<li class="list-group-item quiz-answers" >
<span><label for="id_answers_0"><input type="radio" name="answers_{{question.id}}" value="{{answer.id}}" style="margin-right:10px;" id="{{answer.id}}" required>
{{answer.content}} </label> </span></li>
{% endifequal %}
{% endifequal %}
{% endfor %}
I get the error
Need 2 values to unpack in for loop; got 1.
How can I compare the values so I can select the radio if the key and value matches the question and answer?
Update
{{sitting.items}} in template shows this
{"424": "1529", "437": "1573", "203": "786", "383": "1427", "319": "hi"}
However, when I
{% for key, value in sitting.items %}
<p> {{key}}--{{value}} </p>
<p> {{question.id}}--{{answer.id}} </p>
{% ifequal key question.id %}
{% ifequal value answer.id %}
<li class="list-group-item quiz-answers" >
<span><label for="id_answers_0"><input type="radio" name="answers_{{question.id}}" value="{{answer.id}}" style="margin-right:10px;" id="{{answer.id}}" selected required>
{{answer.content}} </label> </span></li>
{% else %}
<li class="list-group-item quiz-answers" >
<span><label for="id_answers_0"><input type="radio" name="answers_{{question.id}}" value="{{answer.id}}" style="margin-right:10px;" id="{{answer.id}}" required>
{{answer.content}} </label> </span></li>
{% endifequal %}
{% endifequal %}
{% endfor %}
Nothing seems to happpen.

Try:
{% for key, value in sitting.items %}
You need to provide .items when iterating over a dictionary from Python. Good luck!

Related

TypeError at /products/ object of type 'ModelBase' has no len()

So I'm trying to use pagination, When I visit the page I get TypeError at /products/
object of type 'ModelBase' has no len(). The traceback shows this line has the error
books = haha.page(page)
views.py
def showproducts(request):
oof = CartItem.objects.filter(user=request.user).values_list('book', flat=True)
lmao = OrderItem.objects.filter(user=request.user).values_list('book', flat=True)
hehe = CartItem.objects.filter(user=request.user)
category = Category.objects.all()
haha = Paginator(Book, 2)
page = request.GET.get('page')
if page is None:
page = 1
fianlprice = 0
for item in hehe:
fianlprice += item.book.price
# books = Book.objects.all()
books = haha.page(page)
return render(request, 'main/products.html', {'books':books, 'price':fianlprice, 'cart':oof, 'order':lmao, 'category':category})
products.html
<h1>Products</h1>
<h1>{{ error }}</h1>
{% if user.is_authenticated %}
<h1>Your cart currently costs ${{ price }}</h1>
{% else %}
<h1>Please login to view your cart</h1>
{% endif %}
<form method="GET" action="/search/">
<label>Choose a category</label>
<select name="category" id="category">
<option value="All" selected>All</option>
{% for name in category %}
<option value="{{ name.name }}">{{ name.name }}</option>
{% endfor %}
</select>
<input type="text" placeholder="Search here" name="search" id="search">
<button type="submit">Search</button>
</form>
{% for book in books %}
<h3>{{ book.name }}</h3>
<img src= "/media/{{ book.image }}" alt="">
<p>{{ book.description }}</p>
{% if not user.is_authenticated %}
<p>Please login</p>
{% else %}
{% if book.id in cart %}
<form method="POST" action="/removefromcartforhome/">
{% csrf_token %}
<button type="submit" name="removeid" value="{{ book.id }}">remove item from cart</button>
</form>
{% elif book.id in order %}
<h3>You already own this</h3>
{% else %}
<form method="POST" action="/addtocartforhome/">
{% csrf_token %}
<button type="submit" name="bookid" value="{{ book.id }}">Add to cart</button>
</form>
{% endif %}
{% endif %}
{% endfor %}
{% if books.has_other_pages %}
{% if listing.has_previous %}
<li class="page-item">
«
</li>
{% else %}
<li class="page-item disabled">
<a class="page-link">«</a>
</li>
{% endif %}
{% for i in books.paginator.page_range %}
{% if books.number == i %}
<li class="page-item active">
<a class="page-link">{{i}}</a>
</li>
{% else %}
<li class="page-item">
{{i}}
</li>
{% endif %}
{% endfor %}
{% if books.has_next %}
<li class="page-item">
»
</li>
{% else %}
<li class="page-item disabled">
<a class="page-link">»</a>
</li>
{% endif %}
{% else %}
{% endif %}
The paginator needs a QuerySet, not a model, so:
# queryset &downarrow;
haha = Paginator(Book.objects.all(), 2)

Django forloop and all selectable radio buttons

Here is a seemingly simple task, creating a form using a set of records so the user can choose which record to go for, all using a radio button.
<form action="" method="GET">{% csrf_token %}
{% for record in select_records %}
<div class="form-check indent-3">
<label class="form-check-label" for="radio{{forloop.counter}}">
<input type="radio" class="form-check-input" id="radio{{forloop.counter}}" name="{{record.get_model_name}}{{record.id}}" value="{{record.record_name}}">
{% if request.user.userprofile.head_shot_thumb %}
<img src="{{ request.user.userprofile.head_shot_thumb }}" alt="Proforma creator">
{% else %}
<div class="h2-li ">
<i class="fas fa-user"></i>
</div>
{% endif %}
{{ record.record_name }} - {{ record.date_created }}
</label>
</div>
{% endfor %}
The problem is that the form creates a list of radio buttons which are all selectable, just like how all the checkboxes are selectable.
I have searched and compared my code to simple radio forms such as the one at W3schools, but I cannot figure it out. Any help is appreciated.
I did small changes in your code. Check it below.
<form action="" method="GET">
{% csrf_token %}
{% for record in select_records %}
<div class="form-check indent-3">
<label class="form-check-label" for="radio{{forloop.counter}}">
<input type="radio" class="form-check-input" id="radio{{forloop.counter}}" name="record-option" value="{{record.record_name}}">
{% if request.user.userprofile.head_shot_thumb %}
<img src="{{ request.user.userprofile.head_shot_thumb }}" alt="Proforma creator">
{% else %}
<div class="h2-li ">
<i class="fas fa-user"></i>
</div>
{% endif %}
{{ record.record_name }} - {{ record.date_created }}
</label>
</div>
{% endfor %}
</form>
I hope this will help you. :)

About Django pk in urlpattern

I am new to Django, and I am reading one app on github:
https://github.com/rogargon/myrecommendations/blob/web2-html/myrestaurants/urls.py#L18
There is one urlpattern like
url(r'^restaurants/(?P<pk>\d+)/$',
RestaurantDetail.as_view(),
name='restaurant_detail')
It revoke RestaurantDetail view, here: https://github.com/rogargon/myrecommendations/blob/master/myrestaurants/views.py#L36
class RestaurantDetail(DetailView):
model = Restaurant
template_name = 'myrestaurants/restaurant_detail.html'
def get_context_data(self, **kwargs):
context = super(RestaurantDetail, self).get_context_data(**kwargs)
context['RATING_CHOICES'] = RestaurantReview.RATING_CHOICES
return context
Here I know pk is set to one number indicating the id of restaurant, but in the html model, https://github.com/rogargon/myrecommendations/blob/master/myrestaurants/templates/myrestaurants/restaurant_detail.html, I didn't see any where using pk, but the page shows only the one restaurant. Could you how does pk work in this process? How the template know which restaurant I want to show? And why there is no return in this view?
{% extends "myrestaurants/base.html" %}
{% block title %}MyRestaurants - {{ restaurant.name }}{% endblock %}
{% block content %}
<span vocab="http://schema.org/" typeof="Restaurant">
<h1>
<span property="name">{{ restaurant.name }}</span>
{% if user == restaurant.user %}
(edit)
{% endif %}
</h1>
<h2>Address:</h2>
<p>
{{ restaurant.street }}, {{ restaurant.number }} <br/>
{{ restaurant.zipcode }} {{ restaurant.city }} <br/>
{{ restaurant.stateOrProvince }} ({{ restaurant.country }})
</p>
<h2>
Dishes
{% if user.is_authenticated %}
(add)
{% endif %}
</h2>
<ul>
{% for dish in restaurant.dishes.all %}
<li><a href="{% url 'myrestaurants:dish_detail' restaurant.id dish.id %}">
{{ dish.name }}</a></li>
{% empty %}<li>Sorry, no dishes for this restaurant yet.</li>
{% endfor %}
</ul>
<h2>Reviews</h2>
{% if restaurant.restaurantreview_set.all|length > 0 %}
<span rel="aggregateRating">
<p typeof="AggregateRating">
Average rating <span property="ratingValue">{{ restaurant.averageRating|stringformat:".1f" }}</span>
{% with restaurant.restaurantreview_set.all|length as reviewCount %}
from <span property="reviewCount">{{ reviewCount }}</span> review{{ reviewCount|pluralize }}
{% endwith %}
</p>
</span>
<ul rel="review">
{% for review in restaurant.restaurantreview_set.all %}
<li typeof="Review">
<p rel="reviewRating" typeof="Rating">
<span property="worstRating" content="{{ RATING_CHOICES.0.0 }}"></span>
<span property="ratingValue">{{ review.rating }}</span> star{{ review.rating|pluralize }}
{% with RATING_CHOICES|last as best %}
<span property="bestRating" content="{{ best.0 }}"></span>
{% endwith %}
</p>
<p property="description">{% if review.comment %}{{ review.comment }}{% endif %}</p>
<p>Created by <span property="author">{{ review.user }}</span> on
<span property="datePublished" content="{{ review.date|date:'Y-m-d' }}">{{ review.date }}</span></p>
</li>
{% endfor %}
</ul>
{% endif %}
</span>
<h3>Add Review</h3>
<form action="{% url 'myrestaurants:review_create' restaurant.id %}" method="post">
{% csrf_token %}
Message: <textarea name="comment" id="comment" rows="4"></textarea>
<p>Rating:</p>
<p>{% for rate in RATING_CHOICES %}
<input type="radio" name="rating" id="rating{{ forloop.counter }}" value="{{ rate.0 }}" />
<label for="choice{{ forloop.counter }}">{{ rate.1 }} star{{ rate.0|pluralize }}</label>
<br/>{% endfor %}
</p>
<input type="submit" value="Review" />
</form>
{% endblock %}
{% block footer %}
Created by {{ restaurant.user }} on {{ restaurant.date }}
{% endblock %}
The behavior you're asking about ("How the template know which restaurant I want to show") is view behavior, not template behavior.
The template renderer gets passed a restaurant value by the view. The view has no (explicit) return because it's a class-based view - a subclass of DetailView, in particular. DetailView itself inherits standard methods that this view does not override to accept a PK parameter and load a particular instance.
You can read the source code for DetailView to get more of a sense of what's going on, if you like, eg https://github.com/django/django/blob/master/django/views/generic/detail.py - but class-based views are a bit of an advanced topic, and not every project will even use them. I'd focus on other areas first.

edit django form widget rendering

I have a Django form where one of the fields is defined as:
widgets = {
'name': forms.CheckboxSelectMultiple()
}
The template renders them in a loop with:
{% for field in form %}
<fieldset class="article-form__field">
{{ field.label_tag }} {{ field }}
</fieldset>
{% endfor %}
This is rendered as:
<fieldset class="article-form__field">
<label for="category-name_0">Category:</label>
<ul id="category-name">
<li><label for="category-name_0"><input id="category-name_0" name="category-name" type="checkbox" value="GEN" /> General information</label></li>
<li><label for="category-name_1"><input id="category-name_1" name="category-name" type="checkbox" value="FOO" /> Food and drinks</label></li>
</ul>
</fieldset>
In short: <label><input></label>. However, I would like the output to be <label></label><input>.
Is that possible, and if so, how?
Full code is here.
{% for field in form %}
<fieldset class="article-form__field">
{% if field.name != "category-name" %}
{{ field.label_tag }} {{ field }}
{% else %}
{{ field.label_tag }}
<ul id={{ field.auto_id }}>
{% for checkbox in field %}
<li>
<label for="{{ checkbox.id_for_label }}">
{{ checkbox.choice_label }}
</label>
{{ checkbox.tag }}
</li>
{% endfor %}
</ul>
{% endif %}
</fieldset>
{% endfor %}
CheckboxSelectMultiple
RadioSelect (how to customize rendering is described here)

django template syntax to iterate through two lists

I have the following django template, where as I'm iterating through a list (class_list_overall), I want to use forloop.counter0 as an index in another list (classTimeSlots). It just keeps giving me a TemplateSyntaxError. I have tried the following variations:
{{classTimeSlots.{{forloop.counter0}}}}
{{classTimeSlots.[forloop.counter0]}}
{{classTimeSlots.{forloop.counter0}}}
{{classTimeSlots.(forloop.counter0)}}
{{classTimeSlots.forloop.counter0}}
{% with forloop.counter0 as index%}
<legend>{{ classTimeSlots.index}}</legend>
{% endwith %}
None of which worked. Any suggestions? I'm just a newbie at DJango. I'm using Google App Engine.
Here's the code snippet (I know it's inefficient but I've been trying different things):
{% for class_list in class_list_overall %}
<fieldset> <legend>{{ classTimeSlots.forloop.counter0 }}</legend>
<ul>
<li> <label>First Choice </label>
<select class="dropdown" name="class{{forloop.counter}}1" size="1">
<option value="Click Here to Choose" selected="selected">Click Here to Choose</option>
{% for class in class_list %}
<option>{{class}}</option>
{% endfor %}
</select>
</li>
<li>
<label>Second Choice </label>
<select class="dropdown" name="class{{forloop.counter}}2" size="1">
<option value="Click Here to Choose" selected="selected">Click Here to Choose</option>
{% for class in class_list %}
<option>{{class}}</option>
{% endfor %}
</select>
</li>
</ul>
</fieldset>
{% endfor %}
Short answer: you can't do that.
The template language will not try to determine the value of a variable passed in dot syntax.
It will do a literal lookup of forloop.counter0
1: write a template tag that accepts a variable and a key, and have it return the variable[key]
2: this can most likely be done in the view. Can I see it?
Django doesn't support this - it's deliberately limited. Instead, you should modify your view function to zip the two lists together, and pass that in to the template.
Its possible but not recommendable:
{% for class_list in class_list_overall %}
<fieldset> <legend>
{% for cts in classTimeSlots %}
{% ifequal forloop.counter forloop.parentloop.counter %} {{cts}}
{% endifequal %}
{% endfor %} </legend>
<ul>
<li> <label>First Choice </label>
<select class="dropdown" name="class{{forloop.counter}}1" size="1">
<option value="Click Here to Choose" selected="selected">Click Here to Choose</option>
{% for class in class_list %}
<option>{{class}}</option>
{% endfor %}
</select>
</li>
<li>
<label>Second Choice </label>
<select class="dropdown" name="class{{forloop.counter}}2" size="1">
<option value="Click Here to Choose" selected="selected">Click Here to Choose</option>
{% for class in class_list %}
<option>{{class}}</option>
{% endfor %}
</select>
</li>
</ul>
</fieldset>{% endfor %}
But its better to take list into parent dict:
[class_list_overall[i].update({'label':classTimeSlots[i]}) for i in range(0,len(classTimeSlots))]
And then change above code to:
<legend>
{{ class_list.label }}
</legend>

Categories