I seem to know where the issue is located since I can get around it, but for getting around it I have to sacrifice a function I really want to keep.
Here is the relevant code in the non-working state:
{% if sections %}
{% for item in sections %}
<a class="sections" href="{% url 'sections:generate' item.section.slug %}">{{ item.section.title }}</a>
{% for subsection in item.subsections %}
<p>{{ subsection.title }}</p>
{% endfor %}
{% endfor %}
{% else %}
<p>Error retrieving sections or no sections found</p>
{% endif %}
The problem part above is in the link tag. Let me explain by showing the related view.py:
def index(request):
sections = Section.objects.all()
context = {
'sections': [],
}
for section in sections:
context.get("sections").append(
{
'section': section,
'subsections': get_subsections(section),
}
)
return render(request=request, template_name='index.html', context=context)
So, 'sections' is an iterable list of items, containing for every items a dictionary with two entries. One, 'section' and one 'subsection'. There are multiple subsections for every section, this is what I really want to accomplish.
Ordinarily, when not bothering with subsections and simply iterating over a list of sections works fine. The template code for that would look something like:
{% for section in sections %}
{{ section.title }}
{% endfor %}
NOTE! The code above works just fine! But as soon as I add 'sections' as a list of dictionaries and have to reference the slug by item.section.slug the pages stop rendering.
Please advise.
Try using tuples:
View:
context['sections'] = [(section, tuple(get_subsections(section))) for section in sections]
Template:
{% for section, subsections in sections %}
<a class="sections" href="{% url 'sections:generate' section.slug %}">{{ section.title }}</a>
{% for subsection in subsections %}
<p>{{ subsection.title }}</p>
{% endfor %}
{% endfor %}
Related
The title says everything. Two days ago the following code worked fine but now journeys is not set or empty or ...
def map(request, jid):
journeys = None
if request.user.is_authenticated:
journeys = Journey.objects.filter(user_id=request.user.id)
#some stuff
context = {
'jc': len(journeys), #only for testing
'journeys': journeys
}
return render(request, 'JourneyMap/map.html', context)
map.html extends base.html
Inside base.html:
<div class="dropdown-menu" aria-labelledby="dropdown05">
<p>{{ jc }}</p> <-- only for testing
{% for journey in journeys %}
{% if journey.user_id == user.user_id %}
{% if forloop.counter < 4 %}
<a class="dropdown-item"
href="{% url 'JourneyMap_journey' jid=journey.id %}">{{ journey.title }}</a>
{% endif %}
{% endif %}
{% endfor %}
</div>
Result:
It seems like journeys length is 1, so the variable is actually set.
I think that your user check fails here.
{% if journey.user_id == user.user_id %}
What is user.user_id here? Is user another variable that lives somewhere outside of the given context? Then probably it's not set.
Otherwise, if you want to check for current user's id, perhaps you should do:
{% if journey.user_id == request.user.id %}
I have ListBlock called imagesin Wagtail. It works well. If I put
{{ page.images }}
in a template, it render the html code like:
<ul>
<li>item1</li>
<li>item2</li>
</ul>
But I am unable to find out how to get the first item of the list isolated. Or at least how to iterate over the list manually.
I am pretty sure the solution is simple, however I am unable to google it, find in the docs, or understand from the wagtail source.
You haven't shared your model definition, but I'm going to guess it's something like:
class MyPage(Page):
images = StreamField([
('image_list', blocks.ListBlock(blocks.ImageChooserBlock)),
])
Using the standard pattern for manually looping over a StreamField value as shown in the Wagtail docs, this would be:
{% for block in page.images %}
{% if block.block_type == 'image_list' %}
{# at this point block.value gives you the images as an ordinary Python list #}
{# Output the first image using block.value.0: #}
{% image block.value.0 width-800 %}
{# Or loop over block.value manually with a 'for' loop #}
<ul>
{% for img in block.value %}
<li>{% image img width-800 %}</li>
{% endfor %}
</ul>
{% elif block.block_type == 'some_other_block' %}
...
{% else %}
...
{% endif %}
{% endfor %}
In this case, you probably only have one block type defined (image_list), so the if block.block_type == 'image_list' can be left out; but you'll still need the outer {% for block in page.images %}, because StreamField is still defined as a list of blocks, even if you only have one item in that list.
I am using Django 1.8 with Postgres 9.2 on a Windows 8 machine.
I have two pieces of nearly identical code from two of my projects. One works and the other doesn't.
Here's the code that works:
# views.py
from django.shortcuts import render
from models import Artist, Track
def music(request):
artists = Artist.objects.all().order_by('orderName')
artistTrackCollections = []
for artist in artists:
artist.tracks = Track.objects.filter(artist=artist).order_by('order')
artistTrackCollections.append(artist)
return render(request, 'music.html', {'artistTrackCollections': artistTrackCollections,})
And the relevant template code:
{% for artist in artistTrackCollections %}
<dl>
<dt>
{% if artist.website %}
<h2>{{ artist.name }}</h2>
{% else %}
<h2>{{ artist.name }}</h2>
{% endif %}
</dt>
<dd>
<ul>
{% for track in artist.tracks %}
<li>“{{ track.title }}”
<i>({{ track.album.title }})</i>
{% endfor %}
</ul>
</dd>
</dl>
{% endfor %}
Now here's pretty much the exact same code from a different project of mine that doesn't work anymore:
def index(request):
productList = PartModel.objects.filter(isBuild=True, isActive=True).order_by('name')
productCollection = []
for product in productList:
product.part_list = product.buildpart.all().order_by('family__type')[:5]
productCollection.append(product)
return render(request, 'index.html', { 'productCollection': productCollection, })
and its corresponding template:
{% for product in productCollection %}
<p>{{ product.name }}
<p>${{ product.price }}
<ul>
{% for part in product.part_list %}
<li>{{ part.family.type.name }} | {{ part.name }}
{% endfor %}
</ul>
{% endfor %}
This code used to work but now it doesn't. In the code that works I succeed in going through each artist and attaching that artist's tracks. In the code that fails I try to go through each PartModel instance that is a build and get that PartModel instance's corresponding parts. They are identical as far as I can tell. productCollection gets populated but the part_list data for some reason is blank. This leads me to believe the problem is with this line:
product.part_list = product.buildpart.all().order_by('family__type')[:5]
But I cannot discern the difference from this line:
artist.tracks = Track.objects.filter(artist=artist).order_by('order')
Thanks in advance for any help!
This seems like it should be pretty straightforward, but for some reason I am unable to solve this problem. I'm using Django 1.4. I am trying to do a basic check to see if a list QuerySet is empty or not during template rendering, but the if statement I'm using seems always to evaluate to true.
I have a Django template that reads:
{% extends 'includes/base.html' %}
{% if object_list %}
...
{% block data %}
{% for object in object_list %}
...
{{ object.create_date }}
...
{% endfor %}
{% endblock data %}
...
{% endif %}
'base.html' has the block:
<body>
{% block content %}
...
<div class="row-fluid">
<div class="span12">
{% block data %}
<div align="center"><i>No data.</i></div>
{% endblock data %}
</div><!-- span12 -->
</div><!-- row -->
{% endblock content %}
...
</body>
The view function generating the QuerySet is here:
def barcode_track(request, model):
query = request.GET.get('barcode_search', '')
object_list = model.objects.all()
if query:
object_list = model.objects.filter(barcode__icontains=query)
return render_to_response('barcode_track/barcode_list.html',
{'object_list': object_list, 'query': query},
context_instance=RequestContext(request))
Which is called via this form:
<form id="barcode_search_form" method="get" action="" class="form">
<input type="text" name="barcode_search" value="{{ query }}" />
<button type="submit" class="btn">Search</button>
</form>
And the urls.py line:
urlpatterns = patterns('barcode_track.views',
url(r'^$', 'barcode_track', {'model': Barcode},
name="barcode_track"),)
The idea is that results will only be presented if they exist in object_list, and otherwise the parent block will remain unaltered. I have tried changing the name of object_list, and I have printed {{ dicts }} to the page to ensure that object_list is, in fact, empty (which it is). I am not using a generic view, although I realize that the name suggests as much. I have actually had this trouble in a different app I wrote using similar logic, so I must be doing something systematically incorrectly.
What am I missing here?
You can't wrap control flow tags like if around a block. Your problem is that the child template's definition for block data is being used simply because it's there.
You can fix it by placing the if tag inside block data. If you want to inherit the parent's contents when the list is empty, add an else case that expands to {{ block.super }}.
I have the below dictionary with lists of objects.
args = {'Qtag': [
[<Question: Question object>, <Tags: Tags object>],
[<Question: Question object>, <Tags: Tags object>]
]
}
inside my views.py
args=dict(Qtag=Questag)
t=loader.get.template('main.html')
c=Context(args)
and inside my main.html, I am trying to iterate the below way
{%if Qtag %}
{% for item_list in Qtag %}
{% for item in item_list %}
</h4> <b> Question</b>:{{item.qid}} {{item.title}} </h4><br/>
</h4> {{item.question}} </h4>
<button name="tag" type="submit" value="tagname"> {{item.tagname}} </button>
{% endfor %}
{% endfor %}
{% endif %}
When I tried the above way in my main.html, I am getting the things displayed 4 times in the screen. Here, the first list consisting of list of Question object and list of tag object corresponds to a single question and similarly for the other one, so in the screen I only want the two question and its corresponding tags to be displayed. I am not able to iterate properly to get what I need. Any thought on how to achieve this!!!
Thanks.
I'm not sure what args=dict(Qtag=Questag) means in your code (since I don't know what Questag is). I don't know whether your tags are iterable either (I'm assuming so). Your HTML looks malformed too (e.g. I don't see an opening h4).
This is what I'd do to get something similar to what you're looking for. You can work on this.
{% if Qtag %}
{% for question, tags in Qtag %}
{# First put in the question header #}
<h4>Question : {{question.qid}} {{question.title}} </h4>
{# Then the question body #}
<p>
{{question.question}}
</p>
{# Now a tag list #}
<ul>
{% for tag in tags %}
<li>
<button name = "tag" type="submit" value="{{tag.name}}">
{{tag.name}}
</button>
</li>
{% endfor %}
</ul>
{% endfor %}
{% endif %}
Your original solution is iterating over the list quadratically (you're iterating over the list once for every outer iteration) and that's why you're seeing things being printed 4 times.