I would like to have a slightly different navbar depending on whether or not a user is signed in. Additionally, the content of dropdown menus will depend on the user that is logged in.
views.py file:
#app.route('/table')
def my_table:
return render_template("table.html",
user = user,
my_names = my_names)
A page in the application (/table):
{% extends "navbar.html" %}
{% block content %}
<html> A bunch of stuff </html>
The simplified navbar template:
{% extends "bootstrap/base.html" %}
{% import "bootstrap/wtf.html" as wtf %}
{% block navbar %}
<html>
<nav class="navbar navbar-default" role="navigation">
<ul class="dropdown-menu" role="menu">
<li> Signed in as: {{ user }} </li>
<li class="divider"></li>
{% for name in my_names %}
<li> {{ name }} </li>
{% endfor %}
</html>
{% endblock %}
I would like to pass user and my_names to the navbar template. These two data change depending on who is signed in.
Am I thinking about this correctly? Is my structure ok? Should I be using something to simplify this (like Blueprints)?
(I know that I can get the user part by g.user since its global across templates)
Since you are already setting the user on g you have most of what you need already. The only thing left is to set the menu correctly.
The simplest thing to do is to use a context processor:
#app.context_processor
def provide_menu():
menu = derive_menu_from_global_user()
return {'menu': menu}
Then every template will have access to a menu variable containing a list of names that you can iterate over.
Related
I have the following structure of templates:
main.html
<html>
<body>
<p>
This works: {% block title %}{% endblock %}
</p>
{% include 'heading.html' with title=title %} {# but this does not work since it is not a variable #}
</body>
</html>
heading.html
<p>
{{ title }}
</p>
page.html
{% extends 'main.html' %}
{% block title %}test title{% endblock %}
How can I pass the title from page.html to heading.html? Ideally, it should be defined as a block like now, but alternatives are also welcome. I'd like to contain the solution within the templates if possible.
Clarification:
This is a minimal example, but I have multiple pages like main.html that share a larger header that has title and some other variables that I'd like defined in the child template (not necessarily as variable as long as the text is passed).
I could put the title into the view code, but this solution would just decrease the separation of displayed data from the logic.
Use a block around the include with variables, and then wrap {{ block.super }} in the with template tag.
main.html:
<html>
<body>
<p>
This works: {% block title %}{% endblock %}
</p>
{% block with_variables %}
{% include 'heading.html' %}
{% endblock %}
</body>
</html>
page.html:
{% extends 'main.html' %}
{% block title %}test title{% endblock %}
{% block with_variables %}
{% with title="variable title" %}
{{ block.super }}
{% endwith %}
{% endblock %}
You may name it {% block heading %}, or nest the whole main.html in {% block content %}.
instead of {% include %}, you might want to use custom template tags with returning html or extension like slippers
You don't need heading.html. You can use the context variable title directly; as long as you pass it to your render function in your view, e.g.:
views.py
def my_view(request):
context = {'title': 'Hello World!'}
return render(request, 'page.html', context=context)
main.html
<html>
<body>
<p>
This is my title:
{% block title %}{% endblock %}
</p>
</body>
</html>
page.html
{% extends 'main.html' %}
{% block title %}
<strong>{{title}}</strong>
{% endblock %}
If you have administrative rights to your Django installation, an easy and elegant solution would be to switch your Django's template renderer to Jinja2 instead using django-jinja as a backend.
The main advantage of Jinja2 for the needs of this question is that it supports assignment of a block to a variable through block assignments. Since Jinja2 is inspired by the Django template language, your existing templates will need few modifications, if any.
With Jinja2 as a template renderer, you can set the title variable with a block of HTML content in the child template:
page.html
{% extends 'main.html' %}
{% set title %}test title{% endset %}
The title variable will then work in the shared template:
main.html
<html>
<body>
<p>
Main template works: {{ title }}
</p>
{% include 'heading.html' %}
</body>
</html>
And it will also work in the included template:
heading.html
<p>
Included template also works: {{ title }}
</p>
Demo: https://replit.com/#blhsing/AlarmedCleverDebugmonitor
One possible solution is to split heading.html into two and add a {% block %} in-between, but this is an ugly workaround that is prone to bugs with unclosed tags.
I am searching for a better alternative.
main.html
...
{% include 'heading1.html' %} {# containing <p> #}
{% block title %}{% endblock %}
{% include 'heading2.html' %} {# containing </p> #}
...
Additionally, if white spaces are important, there has to be no new line between includes and the block.
add your title to the rendering context and it will be visible in page, main and included heading.
Right now my navbar has an 'if' statement for being authenticated vs not authenticated. My allauth templates are extending from my base and showing these navbars.
Is it possible to add in another 'if' statement for when a user is on an allauth form?
Right now my navbar looks something like this...
<nav class="navbar navbar-expand-lg ml-2 mr-1">
{% if request.user.is_authenticated %}
<a class="navbar-brand d-inline-block align-top rounded-circle ml-1 mr-0" href="{% url 'home' %}">
blah blah blah
{% if request.user.is_superuser %}
<li><a class="nav-item nav-link orange" href="{% url 'management' %}">Site Management</a></li>
blah blah blah
{% endif %}
{% else %}
<a class="navbar-brand d-inline-block align-top rounded-circle ml-2 mr-0" href="{% url 'home' %}">
blah blah blah
{% endif %}
You can use inheritance and define a variable in a parent template together with a block you'll extend in your child template.
For example:
# parent
This is my parent
{% set in_all_auth = True %}
{% block content %}{% endblock %}
This is end of my parent
# child
Here I extend the child by the parent content
{% extends "parent.txt" %}
This is overriding the "content" block from a parent template
{% block content %}
{% if in_all_auth %}
in all auth
{% else %}
not in all auth
{% endif %}
{% endblock %}
Here the block ends
Running:
>>> import jinja2
>>> loader = jinja2.FileSystemLoader(searchpath="./")
>>> env = jinja2.Environment(loader=loader)
>>> print(env.get_template("child.txt").render())
Here I extend the child by the parent content
This is my parent
in all auth
This is end of my parent
>>>
For trimming the space you may utilize the - operator and for not displaying the parent contents you may use additional blocks to disable it with variables.
Or, you can simply extend the rendering by another variable in which you'll set if a user is in the all auth form manually from Python itself.
I'm trying to add a feature to my site where a certain part of the site can be used only by users who confirmed their email account.
I found a solution, but it's not working.
Here is what i did:
I have been suggested to add a separate model for this:
class account_emailconfirmation(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
#property
def has_verified_email(self):
return self.user.emailaddress_set.filter(verified=True,primary=True).exists()
And this is what the template looks like:
{% extends "main/header.html" %}
{% if user.account_emailconfirmation.has_verified_email %}
{% block content %}
<style>
</style>
<body>
<div> <p>Here goes a bunch of features</p> </div>
</body>
{% endblock %}
{% else %}
<p> Your email is ot confirmed </p>
{% endif %}
But it's not working, since i can see the page even without having to confirm my email.
Here is what my db looks like:
There is a table called account_emailconfirmation, then there is an index, verified, that will give 0 when the account is not verified, 1 when it is verified.
Any advice is appreciated!
Write this:
{% extends "main/header.html" %}
{% block content %}
{% if user.profile.has_verified_email %}
<style>
</style>
<body>
<div> <p>Here goes a bunch of features</p> </div>
</body>
{% else %}
<p> Your email is ot confirmed </p>
{% endif %}
{% endblock %}
You need to use the related_name attribute of the account_emailconfirmation.user one to one field
{% if user.account_emailconfirmation.has_verified_email %}
Side note, you should capitalize your classes:
class EmailConfirmation(models.Model):
I assume the account_ portion is for the app. You don't need that, you know which app the model is in.
I have created a template tag in django for forms that only require a submit button, without any other fields (except the hidden csrf field). It can be used as follows:
{% button_only_form "button_text" "action/path" "optionally css classes. %}
I'm currently mainly using this for delete buttons, because delete views require sending a post request, but don't need any other data.
Now I'm finding myself in a situation where I need to dynamically create the action. I'm iterating over a list of items, and the action url for each item would be the result of calling reverse("items:delete", kwargs={"item_id": item.id})
How would I specify this for my template tag? Here's a hugely simplified version of my template:
<ul>
{% for item in items %}
<li>
{{item.title}} - {% button_only_form "Delete" Im_not_sure_how_to_pass_the_action %}
</li>
{% endfor %}
</ul>
You can use the {% url ... as var %} syntax to first create the url for the action and then pass it as a parameter to the button_only_form tag:
<ul>
{% for item in items %}
<li>
{% url "items:delete" item_id=item.id as del_url %}
{{item.title}} -
{% button_only_form "Delete" del_url "..." %}
</li>
{% endfor %}
</ul>
i'm developing a small app with Python and Google app engine. I'm using boilerplate (https://github.com/coto/gae-boilerplate) as front-end which follows gae direction and python templates, so nothing diffrent than plain stuff.
Now, what i would like to have is this.
When a user logged in, if the field of name and last name are not filled in i would like to have, in the home page, the profile editing.
The page for editing the profile is a template (which extend the base.html), called edit_profile.html which works well.
The homepage is a template as well (extend the base.html) called home.html.
Now, can i include the edit_profile.html in home.html? how can i do it?
this is what i've, i don't know what to put instead of ???? i tried with
{% block edit_profile.html %} {% endblock %}
but does not work
{% if user_info.name and user_info.last_name %}
..
{% else %}
????
{% endif %}
thanks.
So you want to include only some block of given template. There are two solutions:
1) Create template just for profile editing form and include it into edit_profile.html. Then include it also into home.html to if condition branch:
profile_form.html:
<form action="{% url some-action %}">
{{ form }}
<input type="submit" value="save"/>
</form
profile_edit.html
{% extends "base.html" %}
{% block main %}
{% include "profile_form.html" %}
{% endblock %}
home.html
{% if user_info.name and user_info.last_name %}
{% include "profile_form.html" %}
{% endif %}
2) use variable for extended template:
profile_form.html
{% extend BASE_TEMPLATE %}
and set it into context w/ different value as needed:
in home.html (let's say included_form.html is some basic template)
{% if user_info.name and user_info.last_name %}
{% with "included_form.html" as BASE_TEMPLATE %}
{% include "edit_profile.html" %}
{% endwith %}
{% endif %}
and if you want show form as a standalone page, set BASE_TEMPLATE to base.html