I have a static homepage, but I'm also using the i18n subsites plugin. So for the homepage I have, in pelicanconf.py:
INDEX_SAVE_AS = 'blog/index.html'
INDEX_URL = 'blog'
and for the English version:
I18N_SUBSITES = {
'en': {
'OUTPUT_PATH': 'output/en/',
'INDEX_SAVE_AS': 'blog/index.html',
'INDEX_URL': 'blog',
}
}
(truncated unnecessary bits)
The problem lies with the translation link for the homepage. The translations macro has:
{% for translation in article.translations %}
{{ translation.lang | lookup_lang_name }}
So for the English-language homepage I could either set the url and output filename as:
<meta name="save_as" content="en/index.html">
<meta name="url" content="en/">
Which makes the translation link go to site.com/en/en/ (and works), or set them as:
<meta name="save_as" content="index.html">
<meta name="url" content="/">
Which conflicts with the standard-language homepage.
Another, related problem is that the index page (blog page) has no translation link to the English or back to the standard-language version whatsoever.
What can I do to solve this?
I was able to solve my problem with the following translations macro:
{% macro translations_for(article) %}
{% if extra_siteurls %}
{% for lang, url in extra_siteurls.items() %}
{% if article %}
{{ lang | lookup_lang_name }}
{% else %}
{{ lang | lookup_lang_name }}
{% endif %}
{% endfor %}
{% endif %}
{% endmacro %}
And by adding a permalink option the each article and page I can also translate the URL for said article or page (otherwise you could just use slug in the above macro).
Last but not least I also removed the url and save_as data from both homepages.
To fix the blog page, I added this to the index.html template:
{% block translation_links %}
{% if lang == 'nl' %}
English
{% else %}
Nederlands
{% endif %}
{% endblock %}
For the second part of your question, have a look at creating language buttons
Related
Need some help, not getting the content from the database not sure why this is happening
using python flask,sqlalchemy with a small sqlite database
I need to see the content from the database displayed on the web page.
At the moment I see only the Home link which is static in the template file.
app.py contains a part of this
#app.route('/page/<int:page_id>')
def view_page(page_id):
page = db.session.query(Pages).filter_by(id=page_id).first()
return render_template('page.html', id=page.id, title=page.title.decode(),
content=page.content.decode())
page.html (this is the template)
{% extends "master.html" %}
{% block content %}
<!DOCTYPE html>
{% for page in pages %}
<h3>{{ page.title.decode() |truncate(150)}}
</h3></a>
<p>{{ page.content.decode() |safe | truncate(350) }}</p>
{% endfor %}
Home
{% endblock %}
</html>
You have to send model with your return template.
#app.route('/page/<int:page_id>')
def view_page(page_id):
pages = Pages.query.all()
return render_template('page.html', pages=pages)
I've created my own theme for Pelican and I've been using it for a while to build my site. I've decided to start blogging again so I'm only now adding the blog features to the site.
I've created my own blog.html template to render the content in the way I want. I started by copying and pasting the code from the 'simple' theme that comes with Pelican to get me started, but even though it is unchanged I'm getting an 'articles_page' is undefined error when I try to build.
Where is the article_page variable set from? I tried adding to my pelicanconf.py file but it didn't help.
{% extends 'base.html' %}
{% block title %}{{ page.title }} — Ricky White{% endblock title %}
{% block content %}
<section class="wrapper">
<div class="container">
<div class="row">
<div class="col">
<ol id="post-list">
{% for article in articles_page.object_list %}
<li><article class="hentry">
<header> <h2 class="entry-title">{{ article.title }}</h2> </header>
<footer class="post-info">
<time class="published" datetime="{{ article.date.isoformat() }}"> {{ article.locale_date }} </time>
<address class="vcard author">By
{% for author in article.authors %}
<a class="url fn" href="{{ SITEURL }}/{{ author.url }}">{{ author }}</a>
{% endfor %}
</address>
</footer><!-- /.post-info -->
<div class="entry-content"> {{ article.summary }} </div><!-- /.entry-content -->
</article></li>
{% endfor %}
</ol><!-- /#posts-list -->
{% if articles_page.has_other_pages() %}
{% include 'pagination.html' %}
{% endif %}
</div>
</div>
</div>
</section>
{% endblock content %}
You must have referenced your template from one of the articles using:
Template: blog
If you remove that reference and add the following lines to your pelicanconf.py, Pelican will generate blog.html directly from your template file:
DIRECT_TEMPLATES = ['index', 'blog']
PAGINATED_DIRECT_TEMPLATES = ['blog']
(Do not forget to empty your output folder before running pelican. Tested on Pelican 3.7.1)
For the sake of future visitors who might come here looking for an answer like I did:
The problem can have a good number of very diverse reasons. In my case it was not a problem with the configuration of the pelican tooling, but rather an error in the metadata of some of my content pages. I had not included the correct category, date or tag fields. You'd never guess that from the error message now, would you?
I found this question looking for the same error.
In my case the reason was an issue which has been closed but not merged in the current release of the Attila theme. More precisely: the error is caused by a template in the templates folder of the theme which has a wrong reference inside it. In the specific case, inside the page template there was a wrong reference to article.
Changing the template manually fixed the issue:
--- a/attila-1.3/templates/page.html
+++ b/attila-1.3/templates/page.html
## -21,8 +21,8 ##
{% else %}
{% set selected_cover = SITEURL+"/"+HEADER_COVER %}
{% endif %}
-{% elif article.color %}
- {% set selected_color = article.color %}
+{% elif page.color %}
+ {% set selected_color = page.color %}
{% elif HEADER_COLOR %}
{% set selected_color = HEADER_COLOR %}
{% endif %}
I hope this helps debugging similar errors.
The page variable articles_page is set in only one place: Writer._get_localcontext and there is a guard condition:
if paginated and template_name in self.settings['PAGINATED_TEMPLATES']:
# ... code ...
paginated_kwargs.update(
{'%s_paginator' % key: paginator,
'%s_page' % key: page, # <-- Creates `article_page`
'%s_previous_page' % key: previous_page,
'%s_next_page' % key: next_page})
If this problem crops up, the easiest solution is to make sure the guard condition evaluates to True. Most likely, the problem is that template_name is not in PAGINATED_TEMPLATES in your configuration file. I opened writers.py, added a print(f"template_name is {template_name}") and got my answer (I didn't have author : None in my PAGINATED_TEMPLATES dictionary).
I have recently taken over the development of a Django/ Python project, and am looking into fixing a particular bug within the system as it currently stands.
There is a database of projects with quite a large amount of information about each project stored. On one of the webpages, there is a button, which when clicked will add a new form to the page- the form allows the user to enter some details about a new object for the given project. If there are existing objects for that project within the database, a 'table' will be displayed with a form on each row for each of the existing objects, and the user can manually update the fields in the form to update the information about each of the objects in the database. They can also add a new 'row' to the 'table' to create a new object to add to that project.
This page is displayed by the view:
def current_ccis(request, budget_id):
"""
View the CCIs for the current budget
"""
budget = Budget.objects.select_related('project').get(id=budget_id)
project = budget.project
ccis = CciItem.objects.select_related('budget', 'budget__project', 'project_room', 'project_room__room').filter(budget_id=budget_id).order_by('project_room__order', 'created')
formset = CciItemFormset(queryset=ccis.exclude(name=None), form_kwargs={'project':project})
context = {
'ccis': ccis,
'project': project,
'budget': budget,
'formset': formset,
'widths': ['60px', '120px', '220px', '120px', '60px', '60px', '60px', '280px', '280px'],
}
return render(request, 'costing/ccis_current.html', context)
The first cell in each form of the formset for each object displays the 'type' of object that it is, and every other cell displays/ stores other information relevant to the object itself.
On another one of the webpages, there is then a report displayed about a given project which includes information based on what the user input into the forms on the page displayed by the view current_ccis(request, budget_id)
This page is displayed by the view:
def report_ccis(request, project_id):
""" CCI items styled for pdf """
project = Project.objects.get(id=project_id)
budget = get_current_budget(project_id)
cci_total_exc = budget.cci_total_exc_vat_final
cci_grouped_items = budget.cci_items.all().order_by('project_room', 'name')
context = {
'project': project,
'cci_total_exc': cci_total_exc,
'cci_grouped_items': cci_grouped_items,
'webview': 1,
}
try: context['current_budget'] = project.budget_versions.get(current_marker=1) #For option name/date on top of pdfs
except ObjectDoesNotExist: pass
if request.GET.get('stage') == 'pd':
""" Render post deposit homepage """
context['html'] = render_to_string('costing/report2_ccis.html', context)
context['active_tab'] = '4'
return render(request, 'costing/reports_post_deposit.html', context)
else:
""" Render pre deposit homepage """
context['html'] = render_to_string('costing/report_ccis.html', context)
context['active_tab'] = '5'
return render(request, 'costing/reports_pre_deposit.html', context)
and the report currently displays the information in the format:
Title
Project ID
Object
detail
detail
Object
detail
i.e. a list of Objects belonging to the project, and underneath 'Object title' a list of details belonging to that object.
The issue that I'm having here, is that for some projects, the 'Object' names are all displayed with their 'details' listed beneath each 'Object', but for others, the details are not listed under their respective 'Objects', but rather all listed under one 'Object', which is titled "None"...
What I don't understand, is why there is this inconsistency- why is that for some projects, the 'Object' names are shown on the report, with all of the 'details' listed under their respective 'Objects', but for other projects, all of the 'details' are listed under the Object 'None'...?
Anyone have any suggestions why this is?
Edit
The reports are displayed in the HTML files with:
(post deposit):
{% block tabs %}
{% with 'Payment schedule,Agreed variations,Variations not yet finalised,Client choice items,Overview'|listify as tabs %}
{% for tab_name in tabs %}
{% with forloop.counter as tab %}
{% if not tab == active_tab|add:0 %}<a class="tab" href="{% url 'costing:report2_tabbed' project.id %}?tab={{tab}}">{% else %}<a class="active tab">{% endif %}{{tab_name}}</a>
{% endwith %}
{% endfor %}
{% endwith %}
{% endblock tabs %}
(pre deposit):
{% block tabs %}
{% with 'Overview, Construction budget, Schedule of works, Client choice items'|listify as tabs %}
{% for tab_name in tabs %}
{% with forloop.counter as tab %}
{% if not tab == active_tab|add:0 %}<a class="tab" href="{% url 'costing:report_tabbed' project.id %}?tab={{tab}}">{% else %}<a class="active tab">{% endif %}{{tab_name}}</a>
{% endwith %}
{% endfor %}
{% endwith %}
{% endblock tabs %}
Edit
The files where this HTML comes from both extend from the same HTML file (reports_tabbed.html), which has the following HTML:
{% extends "base.html" %}
{% load staticfiles utilities %}
{% block head_extras %}
<link rel="stylesheet" type="text/css" href="{% static "moon/scss/pdf-reports.css" %}">
{% endblock head_extras %}
{% block page_options %}
{% if request.user.first_name in 'Becky,Duncan'|listify and project.deposit_received %}
Make quick PDF
{% endif %}
{% endblock page_options %}
{% block content %}
<div class="tabbed m-r-lg text-sm">
<div class="navbar tabbed text-sm">
{% block tabs %}
{% endblock tabs %}
</div>
<div class="tabbed-section border {% block tabbed_class %}page{% endblock tabbed_class %}">
{{html}}
</div>
</div>
{% endblock content %}
{% block content_scripts %}
{% endblock content_scripts %}
I'm working on an Inclusion Tag. In the super shell, the tag returns the appropiate data set nevertheles, I dont see the inclusion template rendered on the calling template. I can only guess the inclusion template is in the wrong location. As of this moment, the template is at MYPROJECT/templates which is the ONLY folder in TEMPLATE_DIRS. Please help me figure out what am I doing wrong here. TIA!
MYPROJECT/newsroom/templatetags/blog_extras.py -> http://pastebin.com/ssuLuVUq
from mezzanine.blog.models import BlogPost
from django import template
register = template.Library()
#register.inclusion_tag('featured_posts.html')
def featured_posts_list():
"""
Return a set of blog posts whose featured_post=True.
"""
blog_posts = BlogPost.objects.published().select_related("user")
blog_posts = blog_posts.filter(featured_post=True)
# import pdb; pdb.set_trace()
return {'featured_posts_list': blog_posts}
MYPROJECT/templates/featured_posts.html -> http://pastebin.com/svyveqq3
{% load blog_tags keyword_tags i18n future %}
Meant to be the the infamous "Featured Posts" Section!
{{ featured_posts_list.count }}
<ul>
{% for featured_post in featured_posts_list %}
<li> {{ featured_post.title }} </li>
{% endfor %}
</ul>
MYPROJECT/settings.py -> pastebin.com/Ed53qp5z
MYPROJECT/templates/blog/blog_post_list.html -> pastebin.com/tJedXjnT
As #Victor Castillo Torres said, you need to change the name of the tag you're loading, which will fix that aspect of your template tag. However, even though they are in different namespaces, I would still change the name of the context variable your tag returns just for sanity:
#register.inclusion_tag('featured_posts.html')
def featured_posts_list():
blog_posts = BlogPost.objects.published().filter(
featured_post=True).select_related("user")
return {'blog_posts': blog_posts}
Then in your template:
{{ blog_posts.count }}
<ul>
{% for blog_post in blog_posts %}
<li>{{ blog_post.title }} </li>
{% endfor %}
</ul>
And finally, in your main template:
{% load blog_extras keyword_tags i18n_future %}
...
{% featured_posts_list %}
I'm relatively new to Django and I'm trying to build up my toolbox for future projects. In my last project, when a built-in template tag didn't do quite what I needed, I would make a mangled mess of the template to shoe-horn in the feature. I later would find a template tag that would have saved me time and ugly code.
So what are some useful template tags that doesn't come built into Django?
I'll start.
http://www.djangosnippets.org/snippets/1350/
Smart {% if %} template tag
If you've ever found yourself needing more than a test for True, this tag is for you. It supports equality, greater than, and less than operators.
Simple Example
{% block list-products %}
{% if products|length > 12 %}
<!-- Code for pagination -->
{% endif %}
<!-- Code for displaying 12 products on the page -->
{% endblock %}
smart-if. Allows normal if x > y constructs in templates, among other things.
A better if tag is now part of Django 1.2 (see the release notes), which is scheduled for release on March 9th 2010.
James Bennet's over-the-top-dynamic get_latest tag
edit as response to jpartogi's comment
class GetItemsNode(Node):
def __init__(self, model, num, by, varname):
self.num, self.varname = num, varname
self.model = get_model(*model.split('.'))
self.by = by
def render(self, context):
if hasattr(self.model, 'publicmgr') and not context['user'].is_authenticated():
context[self.varname] = self.model.publicmgr.all().order_by(self.by)[:self.num]
else:
context[self.varname] = self.model._default_manager.all().order_by(self.by)[:self.num]
return ''
<div id="news_portlet" class="portlet">
{% get_sorted_items cms.news 5 by -created_on as items %}
{% include 'snippets/dl.html' %}
</div>
<div id="event_portlet" class="portlet">
{% get_sorted_items cms.event 5 by date as items %}
{% include 'snippets/dl.html' %}
</div>
I call it get_sorted_items, but it is based on James' blog-post
In come case {% autopaginate queryset %} (http://code.google.com/p/django-pagination/) is useful. For example:
#views.py
obj_list = News.objects.filter(status=News.PUBLISHED)
# do not use len(obj_list) - it's evaluate QuerySet
obj_count = obj_list.count()
#news_index.html
{% load pagination_tags %}
...
# do not use {% if obj_list %}
{% if obj_count %}
<div class="news">
<ul>
{% autopaginate obj_list 10 %}
{% for item in obj_list %}
<li>{{ item.title }}</li>
{% endfor %}
</ul>
</div>
{% paginate %}
{% else %}
Empty list
{% endif %}
Note, that obj_list must be lazy - read http://docs.djangoproject.com/en/dev/ref/models/querysets/#id1