Wagtail / Django ListBlock Behavior - python

I am facing a wired situation, using wagtail.
My Models :
class SlideBlock(blocks.StructBlock):
image = ImageChooserBlock()
caption = blocks.CharBlock(required=False)
class Meta:
template = 'home/blocks/carousel.html'
class HomePageIndex(Page):
body = StreamField([
('head', blocks.TextBlock(classname="full title")),
('text', blocks.RichTextBlock()),
('html', blocks.RawHTMLBlock()),
('slider', blocks.ListBlock(SlideBlock()))
], blank=True)
content_panels = Page.content_panels + [
StreamFieldPanel('body'),
]
# parent_page_types = []
subpage_types = ['home.HomePageIndex',
'blog.BlogPageIndex',
'blog.BlogTagPageIndex']
My Template (MAIN) :
{% with blocks=self.body %}
{% for block in blocks %}
<section>
{% elif block.block_type == 'slider' %}
in
<!-- Gate to an nested template -->
{% include_block block %}
out
{% else %}
block-type not supported
{% endif %}
</section>
{% endfor %}
</article>
{% endwith %}
My Template (nested) :
<div>
<div>
{% for x in block.value %}
<div class="carousel-item">
{% image x.image max-1920x1080 class="d-block w-100" alt="Slide" %}
</div>
{% endfor %}
</div>
</div>
Inside my database i use some test-data for testing reasons... But for some weired reason the nested template is called, as much data is inside my database. So i am not able to iterate over the ListBlock propertly. The output of the given example produces wired repeating outputs...
What did i miss / oversee?

This is because you’re looping twice. Remove the second forloop: {% for x in block.value %}. value should be accessible without the extra loop. You can get the image in your template using value.image instead of x.image

Related

Jinja2 ValueError: too many values to unpack (expected 2)

{%for feed,tim in feeds,time %}
{% set nickname = feed.nick %}
{% set like = feed.like %}
{% set text = feed.text %}
{% set today = tim %}
{% set postid = feed.postid %}
{% set photo = feed.photo %}
{% set profile = feed.profile %}
{%for cmt in cmts %}
{% set nickname = cmt.nick %}
{% set cmt = cmt.cmt %}
{% set cmtid = cmt.cmtid %}
{% if cmtid == postid %}
<p class="description"><span>{{nickname}} </span> {{cmt}}</p>
{% endif %}
{% endfor %}
<div class="comment-wrapper">
<img src="../static/images/smile.PNG" class="icon" alt="">
<input type="text" class="comment-box" id='cmt' placeholder="Add a comment">
<button class="comment-btn" onclick=cmt_write()>post</button>
</div>
</div>
</div>
{% endfor %}
succeeded in executing the for statement with one list in jinja2,
but we have to use two lists.
i try 2 list ( feeds, time ) use in jinja2
how to jinja2 for loop from jinja2
Is there a way to use two lists in jinja2?
If you want to loop over a combined list of two lists (of same length) you have to apply zip function on them. E.g.:
def view_function():
feeds = [...]
time = [...]
feeds_and_time = zip(feeds, time)
# Looks like this: [('feed_1', 'time_1'), ('feed_2', 'time_2')]
Then pass this new feeds_and_time variable to the render function. And in the template, modify the loop:
{% for feed,tim in feeds_and_time %}

How to sort based on a choice field in django in template

Consider the following model:
class Category(models.Model):
name = models.CharField(max_length=100)
description = models.TextField()
POSITIONS = (
('L', 'Left'),
('R', 'Right')
)
position = models.CharField(max_length=1, choices=POSITIONS, default='R')
class Meta:
verbose_name_plural = 'categories'
def __str__(self):
return self.name
I want to sort the objects in a manner such that I can separate the left ones from the right ones and show them in separate parts of the html document. Something like:
{% for category in categories|sort_by: "position" = "left" %}
<ul class="collection with-header">
<li class="collection-header">
<h3>{{category.name}}</h3>
<p><small>{{category.description}}</small></p>
</li>
{% for url in category.extra_link_set.all %}
<li class="collection-item">{{url.url_text}}</li>
{% endfor %}
</ul>
{% endfor %}
I know this wont work. But I am just trying to give an idea as to what I want. Also would the process be similar for any other field type in django models?
You could try something like this:
{% for category in categories %}
<div class="left_stuff">
{% if category.position=='L' %}
<h3>...</h3>
.....
{% endif %}
</div>
{% endfor %}
{% for category in categories %}
<div class="right_stuff">
{% if category.position=='R' %}
<h3>...</h3>
.....
{% endif %}
</div>
{% endfor %}

Django Template - If item == return field from model object

Django 1.10, python 3.5
Hi All!
I have a model, in models.py called "Building_type":
class Building_type(models.Model):
buildingType = models.CharField(max_length=40)
def __str__(self):
return self.buildingType
and a list of buildings that is sent to the django HTML template, called "buildingList", that looks like so:
[
{'name': 'building1', 'type': <Building_type: Blacksmith>},
{'name': 'building2', 'type': <Building_type: Inn>},
{'name': 'building3', 'type': <Building_type: Chemist>},
]
I would like to do this:
{% for building in buildingList %}
{% if building.type == "Inn" %}
<p> this is an Inn </p>
{% endif %}
{% endfor %}
However the IF statement never completes as true.
I have tried the following, all have failed:
{% if building.type == building.type.Inn %}
{% if building.type == Inn %}
{% if building.type == "Inn" %}
If it helps, the following correctly returns "Blacksmith", "Inn", and "Chemist" to HTML:
{% for building in buildingList %}
{% if building.type %}
{{building.type}}
{% endif %}
{% endfor %}
Many thanks if you all can help
If i'm following this correctly shouldn't this work?
{% if building.type.buildingType == "Inn" %}
as type is an instance of a Building_type model which in turn has a field of buildingType so accessing that is type.buildingType

Custom Django Form Not Displaying - Using Wagtail

Wagtail Blog Site - Comment Model Form Issues
I'm creating a blog site, using Wagtail, and I've run in to a snag. I've added a Comment Model to my page, which I can add comments through the admin section and they display on the correct posts, but the comment form I've created is not displaying for some reason. Here's my relevant code. Any tips on where I went wrong would be greatly appreciated.
blog/models.py
class BlogPage(Page):
date = models.DateField("Post date")
intro = models.CharField(max_length=250)
body = RichTextField(blank=True)
#tag manager
tags = ClusterTaggableManager(through=BlogPageTag, blank=True)
#get feature image
def main_image(self):
gallery_item = self.gallery_images.first()
if gallery_item:
return gallery_item.image
else:
return None
search_fields = Page.search_fields + [
index.SearchField('intro'),
index.SearchField('body'),
]
content_panels = Page.content_panels + [
MultiFieldPanel([
FieldPanel('date'),
FieldPanel('tags'),
], heading="Blog information"),
FieldPanel('intro'),
FieldPanel('body'),
InlinePanel('gallery_images', label="Gallery images"),
]
def serve(self, request):
# Get current page
post = self
# Get comment form
form = CommentForm(request.POST or None)
# Check for valid form
if form.is_valid():
comment = form.save(commit=False)
comment.post = post
comment.save()
return redirect(request.path)
return render_to_response(self,
{
'post': post,
'form': form,
},
context_instance=RequestContext(request))
class Comment(models.Model):
post = models.ForeignKey(BlogPage, related_name='comments')
author = models.CharField(max_length=250)
text = models.TextField()
created_date = models.DateTimeField(default=timezone.now)
approved_comment = models.BooleanField(default=False)
def approve(self):
self.approved_comment = True
self.save()
def __unicode__(self):
return self.text
def __str__(self):
return self.text
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('author', 'text',)
blog_page.html
{% extends "base.html" %}
{% load wagtailcore_tags wagtailimages_tags %}
{% block body_class %}template-blogpage{% endblock %}
{% block content %}
<div class="section">
<div class="container">
<h1 class="title">{{ page.title }}</h1>
<p class="meta subtitle">{{ page.date }}</p>
{% with page.main_image as main_image %}
{% if main_image %}{% image main_image fill-500x300 %}{% endif %}
{% endwith %}
<p>{{ main_image.caption }}</p>
<div class="hero-body subtitle">{{ page.intro }}</div>
<div class="content">
{{ page.body|richtext }}
{% if page.tags.all.count %}
<div class="tags">
<h3>Tags</h3>
{% for tag in page.tags.all %}
<span class="tag is-primary is-medium is-link"><a style="color: white" href="{% slugurl 'tags' %}?tag={{ tag }}">{{ tag }}</a></span>
{% endfor %}
</div>
{% endif %}
<p>Return to blog archive</p>
<hr>
<br>
<form action="" method="POST">
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<input class="control button is-primary" type='submit' name='submit' value='Add Comment'>
</form>
<br>
<hr>
<div class="section">
{% if page.comments.all.count %}
<h2 class='subtitle'>Comments</h2>
<div class="comments">
{% for comment in page.comments.all %}
{% if comment.approved_comment %}
<div class="comment">
<h5 class="date">{{ comment.created_date }}</h5>
<strong><h3 class="title is-3">{{ comment.author }}</h3></strong>
<h4 class="subtitle is-5">{{ comment.text|linebreaks }}</h4>
<br>
<hr>
</div>
{% endif %}
{% empty %}
<br>
<p>No comments yet...</p>
{% endfor %}
</div>
{% endif %}
</div>
</div>
</div>
</div>
{% endblock %}
Now I'm getting an error saying:
File "/home/kenneth/development/web/sites/mysite/dynamicsalesops/blog/models.py", line 88, in serve
context_instance=RequestContext(request))
TypeError: render_to_response() got an unexpected keyword argument 'context_instance'
Your view_post function is never used. In Wagtail, rendering pages as HTML is handled by a serve method on the page model itself, not by a separate view function: http://docs.wagtail.io/en/v1.9/reference/pages/theory.html#anatomy-of-a-wagtail-request

django sort dict after query

have a table with websites and a many to one table with descriptions
trying to get a list, firstly getting the latest descriptions and then displaying them ordered by the content of the descriptions...
have the following in views.py
def category(request, category_name_slug):
"""Category Page"""
context_dict = {}
try:
category = Category.objects.get(slug=category_name_slug)
subcategory = SubCategory.objects.filter(category=category)
websites = Website.objects.filter(sub_categories=subcategory, online=True, banned=False)
sites = websites
descriptions = WebsiteDescription.objects.prefetch_related("about")
descriptions = descriptions.filter(about__in=sites)
descriptions = descriptions.order_by('about', '-updated')
descs = []
last_site = "" # The latest site selected
# Select the first (the latest) from each site group
for desc in descriptions:
if last_site != desc.about.id:
last_site = desc.about.id
desc.url = desc.about.url
desc.hs_id = desc.about.id
desc.banned = desc.about.banned
desc.referral = desc.about.referral
descs.append(desc)
context_dict['descs'] = descs
context_dict['websites'] = websites
context_dict['subcategory'] = subcategory
context_dict['category'] = category
except SubCategory.DoesNotExist:
pass
return render(request, 'category.html', context_dict)
this gives me a list with sites and their latest descriptions, so i have the following in category.html
{% if category %}
<h1>{{ category.name }}</h1>
{% for subcategory in category.subcategory_set.all %}
{{ subcategory.name }} ({{ subcategory.website_set.all|length }})
{% endfor %}
{% if descs %}
{% load endless %}
{% paginate descs %}
{% for desc in descs|dictsortreversed:"description"|dictsortreversed:"officialInfo" %}
<ul id='list' class='linksteps'>
<a href="/{{ desc.about_id }}" rel="nofollow" target="_blank">
<img src="/static/screenshots/{{ desc.about_id }}.png" />
</a>
<li><h3>{{ desc.about_id }}{% if desc.title %} - {{ desc.title }} {% endif %}</h3>
{% if desc.description %}<b>Description: </b>{{ desc.description }}
<br />{% endif %} {% if desc.subject %}<b>Keywords: </b>{{ desc.subject }}
<br />{% endif %} {% if desc.type %}<b>Type: </b>{{ desc.type }}
<br />{% endif %} {% if desc.officialInfo %} {% if desc.language %}<b>Language: </b>{{ desc.language }}
<br />{% endif %} {% if desc.contactInformation %}<b>Contact info: </b>{{ desc.contactInformation }}
<br />{% endif %}
{% else %}
{% endif %}
</li>
</ul>
</div>
{% endfor %}
{% show_pages %}
{% else %}
<strong>No websites currently in category.</strong>
{% endif %}
{% else %}
The specified subcategory {{ category_name }} does not exist!
{% endif %}
Initially i used dictsort
{% for desc in descs|dictsortreversed:"description"|dictsortreversed:"officialInfo"|dictsortreversed:"referral" %}
to give me the list in the desired order, so i was all happy ;)
Then however i decided i needed some pagination because the lists became too long.
django-endless-pagination works fine and does what its supposed too, however it splits up my list before the dictsort kicks in.
is there a way to sort before pagination happens and after i ordered_by at the initial query to have the latest descriptions selected?
much obliged
EDIT:
not getting any answers so my question might not be clear.
as far as i understand i need to sort the values in context_dict at the end in views.py replacing the dictsort as in the template
SOLVED:::
doing this did the trick for me to replace the dictsort.
descs1 = sorted(descs, key=operator.attrgetter('referral', 'officialInfo', 'description'), reverse=True)
context_dict['descs'] = descs1
SOLVED:::
doing this did the trick for me to replace the dictsort.
descs1 = sorted(descs, key=operator.attrgetter('referral', 'officialInfo', 'description'), reverse=True)
context_dict['descs'] = descs1

Categories

Resources