How to set up a custom template in djangocms - django

I've successfully installed djangocms on a Ubuntu machine, and now I would like to integrate a custom template bought from Envato.
After I have installed it, djangocms came with its own simple template files which are located in mysite/templates:
base.html
{% load cms_tags staticfiles sekizai_tags menu_tags %}
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>{% block title %}This is my new project home page{% endblock title %}</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.4/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.4/css/bootstrap-theme.min.css">
{% render_block "css" %}
</head>
<body>
{% cms_toolbar %}
<div class="container">
<div class="navbar navbar-default" role="navigation">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Project name</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
{% show_menu 0 1 100 100 "menu.html" %}
</ul>
</div>
</div>
{% block content %}{% endblock content %}
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.4/js/bootstrap.min.js"></script>
{% render_block "js" %}
</body>
</html>
feature.html
{% extends "base.html" %}
{% load cms_tags %}
{% block title %}{% page_attribute "page_title" %}{% endblock title %}
{% block content %}
<div class="jumbotron">
{% placeholder "feature" %}
</div>
<div>
{% placeholder "content" %}
</div>
{% endblock content %}
menu.html
{% load i18n menu_tags cache %}
{% for child in children %}
<li class="{% if child.ancestor %}ancestor{% endif %}
{% if child.selected %} active{% endif %}
{% if child.children %} dropdown{% endif %}">
{% if child.children %}
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
{{ child.get_menu_title }} <span class="caret"></span>
</a>
<ul class="dropdown-menu">
{% show_menu from_level to_level extra_inactive extra_active template "" "" child %}
</ul>
{% else %}
<span>{{ child.get_menu_title }}</span>
{% endif %}
</li>
{% if class and forloop.last and not forloop.parentloop %}{% endif %}
{% endfor %}
page.html
{% extends "base.html" %}
{% load cms_tags %}
{% block title %}{% page_attribute "page_title" %}{% endblock title %}
{% block content %}
{% placeholder "content" %}
{% endblock content %}
I have read their documentation but I haven't found anything related to some custom template integration. Could anyone please lead me in the right direction ?
EDIT1:
I have added in CMS_TEMPLATES:
CMS_TEMPLATES = (
## Customize this
('page.html', 'Page'),
('feature.html', 'Page with Feature'),
('index.html', 'oriel.io') # this is what I added
)
but nothing happened.

Add your templates to CMS_TEMPLATES in your settings file.

I recently met the same problem! So let me try to explain
1) You should extend PageAdmin in admin.py
In admin side, when you want to choose template for page ('advanced settings') it will call AdvancedSettingsForm by default. but we must to extend too to give your templates.
class ExtendedPageAdmin(PageAdmin):
def get_form_class(self, request, obj=None, **kwargs):
if 'advanced' in request.path_info:
return ExtendedAdvancedSettingsForm
elif 'permission' in request.path_info:
return PagePermissionForm
elif 'dates' in request.path_info:
return PublicationDatesForm
return self.form
and DO NOT forget unregister and register
admin.site.unregister(Page)
admin.site.register(Page, ExtendedPageAdmin)
2) OK) You have choosen ('advanced settings') and there must be choice among your custom templates.
class ExtendedAdvancedSettingsForm(AdvancedSettingsForm):
def __init__(self, *args, **kwargs):
super(ExtendedAdvancedSettingsForm, self).__init__(*args, **kwargs)
template_choices = [(x, _(y)) for x, y in get_cms_setting('TEMPLATES')]
self.fields['template'] = forms.ChoiceField(choices=template_choices)
3) Ok, wee see custom templates for page, but there will be error if you want to save it. It's because of Page model. It looks like this:
#python_2_unicode_compatible
class Page(six.with_metaclass(PageMetaClass, MP_Node)):
"""
A simple hierarchical page model
"""
...
template_choices = [(x, _(y)) for x, y in get_cms_setting('TEMPLATES')]
...
template = models.CharField(_("template"), max_length=100,
choices=template_choices, default=TEMPLATE_DEFAULT
help_text=_('The template used to render the content.'))
4) So you should change template_choice during init the Page object. Let's use signals
def after_page_init(sender, instance, **kwargs):
instance._meta.get_field_by_name('template')[0]._choices = []
def patch_cms_page():
from cms.models import Page
from django.db.models.signals import post_init
post_init.connect(after_page_init, sender=Page)
and finally call patch_cms_page() in urls.py )

Related

Flask.flash messages not available through extended template

I am having trouble with sending flashed messages to a route that extends its layout from another template. This message shows up just fine if use the message in the layout.html which makes me believe that rendering login.html first will render layout.html and use the flashed message there and not pass it to my /login route. How are you able to call this message in an extended template? I am using the jijna with syntax taken from here to be able to have the message variable available within my mainblock. Flask's documentation does not specify this either.
app.py
#app.route("/login", methods=["POST", "GET"])
def login():
# Forget any previous user
if session.get("user_id"):
session.pop("user_id")
if request.method == "POST":
# Create connection cursor
cursor = mysql.connection.cursor()
# Query database for email
cursor.execute("SELECT id, email, password FROM users WHERE email = %s", [request.form.get("email")])
row = cursor.fetchone()
print(row)
if row is None:
print("WHY")
flash("Invaid user")
return redirect("login")
My layout.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Hoook - {% block title %}{% endblock %}</title>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0, width=device-width">
<link href="/static/favicon-16x16.png" rel="icon">
<link href="/static/style.css" rel="stylesheet">
<!-- Scripts -->
<script src="https://kit.fontawesome.com/542c2d099e.js" crossorigin="anonymous"></script>
<script src="/static/mainJS.js"></script>
</head>
<body>
<div class="page-wrapper">
<header>
<nav class="main-navbar">
{% if request.path == "/login" %}
<div class="navbar-container login-container">
{% else %}
<div class="navbar-container">
{% endif %}
<div>
{% if request.path == "/login" %}
<img src="/static/hoook_logo_blue.png" alt="Hoook Logo" height="50" width="150">
{% else %}
<img src="/static/hoook_logo.png" alt="Hoook Logo" height="50" width="150">
{% endif %}
</div>
{% if request.path != "/login" %}
<div>
{% if session["user_id"] %}
{# change nav bar for logged in users #}
{% else %}
{# work on this nav bar for unlogged in users #}
{% if request.path == "/signup" %}
<a class="navbar-link" href="/login">Sign in</a>
{% endif %}
{% endif %}
</div>
{% endif %}
</div>
</nav>
</header>
</div>
<main>
{% if request.path == "/login" %}
<div class="top-container signup-container">
{% else %}
<div class="top-container">
{% endif %}
{% with messages = get_flashed_messages() %}
{% block main %}{% endblock %}
{% endwith %}
</div>
</main>
<footer>
</footer>
</body>
</html>
My login.html
{% extends "layout.html" %}
{% block title %}
Login
{% endblock %}
{% block main %}
<div class="login-div">
<div>
<h1 class="color-control">Sign in to Hoook</h1>
</div>
<div class="login-input-bx">
<form action="/login" method="post" autocomplete="off">
<div class="form-control login-form-control">
<label class="login-label color-control" for="email">Email address</label>
<input class="login-input" type="text" name="email" id="email" required autofocus>
</div>
<div class="form-control login-form-control">
<label class="login-label color-control" for="password">Password</label>
<input class="login-input" type="password" name="password" id="password" required readonly onfocus="this.removeAttribute('readonly')">
</div>
<button class="btn btn-login" type="submit">Sign in</button>
</form>
</div>
{% if messages %}
{% for msg in messages %}
<div class="flashed-messages-div">
<p class="signup-para" id="login-flashed-messages">Error: {{ msg }}</p>
</div>
{% endfor %}
{% endif %}
<div class="signup-link-div">
<p class="color-control signup-login-font">New to Hoook? <a class="signup-link-anchor" href="/signup">Create an account</a>.</p>
</div>
</div>
{% endblock %}
Update
I guess I could do something like make_response instead as seen here. and just use:
response = make_response(render_template("login.html", message = "Invalid user"), 302)
return response
However I am curious if there is a way to pass the flashed message through instead.
I have had the same issue. Instead of:
return redirect("login")
try with:
return render_template("login.html")
The flashed message works that way for me.

Problem importing bootstrap templates in flask

I'm new to flask and right after starting a training I hit the wall...
There's the following project structure:
flask_project_directory
|
+- start.py
|
+- [templates]
|
+- [bootstrap]
| |
| +- base.html
|
+- 404.html
+- 500.html
+- base.html
+- index.html
+- user.html
As you see, there are two base.html files, both contain different source code. But let's start from the top.
start.py:
from flask import Flask, render_template
from flask_bootstrap import Bootstrap
app = Flask(__name__)
bootstrap = Bootstrap(app)
#app.route('/')
def index():
return render_template('index.html')
#app.route('/user/<name>')
def user(name):
return render_template('user.html', name=name)
#app.errorhandler(404)
def page_not_found(e):
return render_template('404.html'), 404
#app.errorhandler(500)
def internal_server_error(e):
return render_template('500.html'), 500
app.run(debug=True)
templates/bootstrap/base.html:
<!DOCTYPE html>
<html>
<head>
{% block scripts %}
{% endblock %}
{% block head %}
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>{% block title %}Test-{% endblock %}-app</title>
{% endblock %}
</head>
<body>
{% block content %}
<div class="container">
{% block page_content %}{% endblock %}
</div>
{% endblock %}
</body>
</html>
templates/base.html:
{% extends "bootstrap/base.html" %}
{% block title %}- app{% endblock %}
{% block head %}
{% endblock %}
{% block navbar %}
<div class="navbar navbar-inverse" role="navigation">
<div class="container">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navbar</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">START</a>
</div>
<div class="navbar-collapse collapse">
<ul class="navbar navbar-nav">
<li>Home Page</li>
</ul>
</div>
</div>
{% endblock %}
{% block content %}
<div class="container">
{% block page_content %}{% endblock %}
</div>
{% endblock %}
index.html:
{% extends "base.html" %}
{% block page_content %}
<div class="page-header">
<h3>Hi there!</h3>
</div>
{% endblock %}
user.html:
{% extends "base.html" %}
{% block title %}-app{% endblock %}
{% block page_content %}
<div class="page-header">
<h3>Hi, {{ name }}!</h3>
</div>
{% endblock %}
The problem is, although both index.html and user.html extend templates/base.html, the code from templates/bootstrap/base.html which defines the navbar and related components is nowhere to be found. Also, the templates/base.html can't be seen anywhere. In fact, the app processes the user name correctly if it's defined, there's a greeting if the URL points to the index.html page, also the 404 error gets handled correctly, but there are no bootstrap components loaded. Also, there's no bootstrap styling at all, the base font is Times New Roman.
Is there anything with absolute paths or so? I have to add that before splitting the code to fulfill DRY assumptions everything was working correctly. It looks like I messed up with imports but have no idea where.
As soon as you have initialized bootstrap, the template "bootstrap/base.html" becomes available and can be referenced from your application's templates using the extends keyword. This you have done.
You can have only the templates/base.html template. You do not need templates/bootstrap/base.html.
Your templates/base.html looks generally fine and healthy. With a few modifications, you can have the remaining features that are in templates/bootstrap/base.html:
{% extends "bootstrap/base.html" %}
{% block title %}
<!-- You do not need to define your meta tags here -->
<!-- Simply add your title -->
<title>Test</title>
{% endblock %}
{% block head %}{% endblock %}
{% block navbar %}
<div class="navbar navbar-inverse" role="navigation">
<div class="container">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navbar</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">START</a>
</div>
<div class="navbar-collapse collapse">
<ul class="navbar navbar-nav">
<li>Home Page</li>
</ul>
</div>
</div>
{% endblock %}
{% block content %}
<div class="container">
{% block page_content %}{% endblock %}
</div>
{% endblock %}
{% block scripts %}{% endblock %}
title, head, navbar, content and scripts blocks are implementations of bootstrap/base.html.

Start the Page Menu not from root_page, rather from second level

I have a page tree wich begins with 3 pages:
/private
/business
/education
in each of those pages there are several other pages inside.
Like as the wagtail demosite i built a templatetag to implement the top navigaton in my base template. the special thing is, that my menu is splitted in two sections: the first level (private, business, education) is shown up on the top of my website (section menu) and the child elements of those pages lies in my bootstrap navbar (top menu). how can i tell the top_menu model to ignore the first level, because its allready shown in my section menu?
menu_tags.py
from django import template
register = template.Library()
#register.assignment_tag(takes_context=True)
def get_site_root(context):
return context['request'].site.root_page
def has_menu_children(page):
return page.get_children().live().in_menu().exists()
#register.inclusion_tag('tags/section_menu.html', takes_context=True)
def section_menu(context, parent, calling_page=None):
menuitems_section = parent.get_children().filter(
live=True,
show_in_menus=True
)
return {
'calling_page': calling_page,
'menuitems': menuitems_section,
# required by the pageurl tag that we want to use within this template
'request': context['request'],
}
#register.inclusion_tag('tags/top_menu.html', takes_context=True)
def top_menu(context, parent, calling_page=None):
menuitems = parent.get_children().filter(
live=True,
show_in_menus=True
)
for menuitem in menuitems:
menuitem.show_dropdown = has_menu_children(menuitem)
return {
'calling_page': calling_page,
'menuitems': menuitems,
# required by the pageurl tag that we want to use within this template
'request': context['request'],
}
# Retrieves the children of the top menu items for the drop downs
#register.inclusion_tag('tags/top_menu_children.html', takes_context=True)
def top_menu_children(context, parent):
menuitems_children = parent.get_children()
menuitems_children = menuitems_children.live().in_menu()
return {
'parent': parent,
'menuitems_children': menuitems_children,
# required by the pageurl tag that we want to use within this template
'request': context['request'],
}
section_menu.html
{% load menu_tags wagtailcore_tags %}
{% for menuitem in menuitems %}
<li class="{% if calling_page.url == menuitem.url %} active{% endif %}">
{{ menuitem.title }}
</li>
{% endfor %}
top_menu.html
{% load menu_tags wagtailcore_tags %}
{% get_site_root as site_root %}
{% for menuitem in menuitems %}
<li class="{% if menuitem.show_dropdown %}dropdown{% endif %}{% if menuitem.active %} active{% endif %}">
{% if menuitem.show_dropdown %}
<a data-toggle="dropdown" class="dropdown-toggle" href="#">{{ menuitem.title }} <b class="caret"></b></a>
{% top_menu_children parent=menuitem %}
{% else %}
{{ menuitem.title }}
{% endif %}
</li>
{% endfor %}
header.html (where my section menu lies)
<header class="ms-header ms-header-dark">
<div class="departement-switcher">
<div class="container">
<ul>
{% block menu %}
{% get_site_root as site_root %}
{% section_menu parent=site_root calling_page=self %}
{% endblock %}
</ul>
</div>
</div>
</header>
navbar.html (where my default menu lies)
{% load menu_tags static %}
<nav class="navbar navbar-static-top yamm ms-navbar ms-navbar-dark">
<div class="container container-full">
<div class="navbar-header">
<a class="navbar-brand" href="/">
<img src="{% static 'img/logo.svg' %}" alt="Data Quest AG">
</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
{% block menu %}
{% get_first_level as site_root %}
{% top_menu parent=site_root calling_page=self %}
{% endblock %}
</ul>
</div>
<a href="javascript:void(0)" class="sb-toggle-left btn-navbar-menu">
<i class="zmdi zmdi-menu"></i>
</a>
</div>
</nav>

Django, trying to change the class attribute of an extended nav bar

I created a "base.html" template to hold my nav bar and other elements that are recurrent on my website.
When I extend this template and put values into my blocks one of them doesn't want to work properly.
In my code I try to set the class value of my nav element to "active" depending on which page I'm in (it might not be the best solution). This block never works.
Thank you for your help :)
urls.py
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^addProduct/$', views.addProduct, name='addProduct'),
]
views.py
def index(request):
latest_product_list = Product.objects.all().order_by('-id')[:5]
return render(request, 'main/index.html', {'latest_product_list': latest_product_list})
def addProduct(request):
# Do things
return render(request, 'main/add_product.html', {'form':form})
base.html
<!DOCTYPE html>
<html lang="fr">
<head>
#header informations
</head>
<body>
<div class="container-fluid">
<div class="row">
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
</div>
<ul class="nav nav-pills" role="tablist">
<li role="presentation" class="{% block navbar_class-index %}{% endblock %}">Index</span></li>
<li role="presentation" class="{% block navbar_class-addProduct %}{% endblock %}">Ajouter un produit</li>
</ul>
<div class="row" id="content">
{% block content %}{% endblock content %}
</div>
</div>
</body>
index.html
{% extends "base.html" %}
{% block navbar_class-index %}active{% endblock %}
{% block content %}
<div class="col-md-12">
## Here is my content
</div>
{% endblock content %}
add_product.html
{% extends "base.html" %}
{% block navbar_class-addProduct %}active{% endblock %}
{% block content %}
<div class="col-md-12">
<form action="{% url 'main:addProduct' %}" method="post">
{% csrf_token %}
<label> Entrez votre produit et cliquez sur Add Product.</label><br/><br/>
<label> Produit : </label>{{form.form_product_url}}
<input type="submit" value="Add Product" />
</form>
</div>
{% endblock content %}
I guess your base.html file is not in the correct folder !

Get length of an item passed in request (and context) (django-breadcrumbs)

I am using this django-plugin here: https://github.com/chronossc/django-breadcrumbs
But I can't seem to be able to check in the templates if there is actually an array of breadcrumbs or not… I have tried:
{%if request.breadcrumbs%} {% if request.breadcrumbs|length > 0%}
and so on… but nothing truly tells me if there are some or not.
I want this bar to appear if I passed in breadcrumbs, and not appear in the case that I didn't pass some breadcrumbs in my view:
{% if request.breadcrumbs|length > 0 %}
<div class="navbar navbar-fixed-top" style="top:38px;z-index:1029;" id="breadcrumb-sticky-header">
<div class="container">
<div class="container-fluid">
<div class="row-fluid">
<ul id="breadcrumb-sticky-header-inner" class="breadcrumb">
{% for breadcrumb in request.breadcrumbs %}
{% if not forloop.last %}
<li>{{ breadcrumb.name }} <span class="divider">/</span></li>
{% else %}
<li class="active">{{ breadcrumb.name }}</li>
{% endif %}
{% endfor %}
</ul>
</div>
</div>
</div>
</div>
{% endif %}
Here is the code in my view:
#login_required
def view(request, t_id):
try:
tshoot = Troubleshoot.objects.select_related('category', 'equipment', 'equipment__model').get(pk=t_id)
request.breadcrumbs([
(("%s: %s" % (tshoot.equipment.model.name, tshoot.equipment.serial)),
'/equipment/view/%s/' % (tshoot.equipment.id)),
(("%s" % (tshoot.category.name)),
'/troubleshoot/categories/view/%s/' % (tshoot.category.id)),
((tshoot.title), '')
])
Based on the code in the django-breadcrumbs project (line 191 in breadcrumbs.py: https://github.com/chronossc/django-breadcrumbs/blob/master/breadcrumbs/breadcrumbs.py#L191), It looks like they've implemented a .all() method.
You should be able to use the |length template filter on the results of the .all() method to get the result you want, like so:
{% if request.breadcrumbs and request.breadcrumbs.all|length > 0 %}
I have not tested this; this is what my quick code inspection revealed.
Not sure what request.breadcrumbs|length > 0 does, but I would use the sample template:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>Breadcrumbs test page | {% for b in request.breadcrumbs %}{{ b.name }}{% if not forloop.last %} > {% endif %}{% endfor %}</title>
</head>
<body>
{{ request.breadcrumbs }}
<p>Breadcrumb: {% for b in request.breadcrumbs %}{{ b.name }}{% if not forloop.last %} / {% endif %}{% endfor %}</p>
<p>Links: <a href='/'>Home</a> | <a href='/someview/'>Breadcrumb in view</a> | <a href='/flat01/'>Flatpages</a>
<p>Content: <br>
{% if text %}{{ text }}{% endif %}
{% if flatpage %}{{ flatpage.content }}{% endif %}
</body>
</html>
and view until you are comfortable with how it works:
# Create your views here.
from django.shortcuts import render_to_response
from django.template.context import RequestContext
def home(request):
print request.breadcrumbs
return render_to_response('home.html',
{'text': 'Hello, this is home!'},
context_instance=RequestContext(request))
def someview(request):
request.breadcrumbs('just a view to show some url', request.path)
return render_to_response('home.html',
{'text': 'Hello, this is some second view'},
context_instance=RequestContext(request))
(from: https://github.com/chronossc/django-breadcrumbs/blob/master/breadcrumbs_sample)