Link to a page in django cms, first check if it exists - python

I often do things like this in a django template, with django-cms:
{% load cms_tags %}
Imprint
On production, this fails silently, and the href attribute is empty. On development, I'm forced to insert the page with id "imprint", otherwise I get a "DoesNotExist" exception.
How can I improve this situation? Maybe I'm looking for something like
{% if 'imprint'|cms_page_exists %}
...the link and stuff...
Is there a known best practice for this (not quite seldom) use case? Or do you all use it as shown first?

You could assign a tag result to a variable and then check is it empty:
{% page_url 'imprint' as url %}
{% if url %}
Imprint
{% endif %}
Other ways imply creating your own template tag or filters, so the above is the simplest one IMHO.
See also an example in the docs.

Related

Django wildcard in request.path

don't know much about django but trying to resolve something quickly for a client, they want some content to only show up on certain pages but the code is nav (used across all pages) hence was trying to add:
{% if request.path == '/*/projects/' %} something {% endif %}
but this doesn't work. Each project has a unique number, hence unique url, but I cannot do:
{% if 'projects' in request.path %} something {% endif %}
as some pages on the site contain "projects" in the url where we do not want "something" showing. Hence I wanted to use a simple * as wildcard in url, but this does not work.
Many thanks!

Django Templates: How to filter based on the URL?

I have a common header used throughout the site. On some pages, based on the URI we're at, I'd like to include/exclude some html content. What would be the proper way to do it? I see a 'url' tag but that obviously isn't it (doesn't seem to work for me at all in fact, on Django 1.5.5). I was hoping for a simple filter, something like:
{% if url == '/dashboard/' %}
<!-- conditional html content -->
{% endif %}
I know that I could pass some custom data from the View action via its context, then check against it in the template, but that feels a bit.. excessive/iffy (?)
You can use request.path in the template to get the current url like so:
{% if request.path == '/dashboard/' %}
<!-- conditional html content -->
{% endif %}
For this to work you must have django.core.context_processors.request listed in your TEMPLATE_CONTEXT_PROCESSORS in your settings.py file.

Flask and jinja2 include tag

How to do it "include tag" in jinja2. I need to output a block of articles in the base template. And they work in children.
views.py
Articles.query.filter_by(name=name).first()
base.html
{% block content %}
Content base
{% endblock %}
---{{ this_articles_tag }}----
children.html
{% extends 'base.html' %}
{% block content %}
Content children
{% endblock %}
---{{ output Articles }}----
Django in this "include tag", how to do it in jinja2? (Without using context_processor)
If you need to include another template in the template, just use include in Jinja. But if you are talking about template tags (in Django I remember I liked them a lot), then in Flask only your mentioned context_processor is the way to go. Which I think is not a bad thing at all.
Edit:
Easiest way to get context processor registered as a function is pointed in the documentation.
But if you want something more fancy, like dynamic loader or you will load your functrion from different places, then you can define your own decorator function, which basically wraps the function which returns dictionary:
def example_templatetag():
def get_something():
return get_want_you_want_from_db()
return dict(get_something=get_something)
Then where you create your Flask app object you can easily register this function:
app.context_processor(example_templatetag)
And then in a template you can use is like:
{% set data_you_wanted=get_something() %}
{{ data_you_wanted }}
But maybe for you the way mentioned in documentation will be more than enough ;)

Django template check for empty when I have an if inside a for

I have the following code in my template:
{% for req in user.requests_made_set.all %}
{% if not req.is_published %}
{{ req }}
{% endif %}
{% empty %}
No requests
{% endfor %}
If there are some requests but none has the is_published = True then how could I output a message (like "No requests") ?? I'd only like to use Django templates and not do it in my view!
Thanks
Even if this might be possible to achieve in the template, I (and probably many other people) would advise against it. To achieve this, you basically need to find out whether there are any objects in the database matching some criteria. That is certainly not something that belongs into a template.
Templates are intended to be used to define how stuff is displayed. The task you're solving is determining what stuff to display. This definitely belongs in a view and not a template.
If you want to avoid placing it in a view just because you want the information to appear on each page, regardless of the view, consider using a context processor which would add the required information to your template context automatically, or writing a template tag that would solve this for you.

Jinja's loop variable is not available in include-d templates

I have code similar to the following in one of my jinja template
{% for post in posts %}
{% include ["posts/" + post.type + ".html", "posts/default.html"] %}
{% endfor %}
which is supposed to render each post inside the posts collection, depending on the .type of the post. I have a different template setup for each post.type. And for those I don't have a template, it reverts to the default post template.
Now, I want the index of the post being displayed from bottom, inside the post templates, which is provided by loop.revindex. But for some reason, if I use loop.revindex inside the post template, I get a error saying UndefinedError: 'loop' is undefined.
So, is loop not available in the included templates? Is this by design? Am I doing something wrong with how I organised my templates for this to be not available?
Edit Okay, I came up with a workaround, in the for loop, before I include my template, I do
{% set post_index = loop.revindex %}
and use post_index inside the post template. Not ideal, but seems like the only way. I still want to know your solutions though.
Edit 2 One other thing, I am able to access the post variable inside the included template, but not the loop variable.
If might be possible with the {% with %} statement.
Try this:
{% with %}
{% set loop_revindex = loop.revindex %}
{% include ... %}
{% endwith %}
Instead of using loop.revindex in the included template, use loop_revindex.
Another option is to pass the entire loop variable into the included template by setting a local variable to loop
{% for post in posts %}
{% set post_loop = loop %}
{% include ["posts/" + post.type + ".html", "posts/default.html"] %}
{% endfor %}
This gives you access to all of the loops properties, and, to me, makes it more clear in the included template what the variable is.

Categories

Resources