I've been trying to use my custom 404- and 403 pages for my django project and I used code for it that I already used in other projects, but somehow it's not working yet.
This is my function:
def error_404(request, exception):
return render(request, 'main/errors/404.html', status=404)
And this is where i call the function in the urls.py:
handler404 = 'main_app.views.error_404'
This is my 404.html:
{% extends "../base.html" %}
{% load static %}
{% load i18n %}
<html>
<header>
{% block title %}<h1>404 - {% trans "Page not found" %}</h1>{% endblock %}
</header>
<main>
{% block content %}
<p>The page your looking for could not be found</p>
{% endblock %}
</main>
</html>
The pathes should actually be fine, since I used render(template_name=) alot in this project and I just copied it and changed the file name. I also set the DEBUG=False in the settings.py
Does anybody have an idea?
As far as I know, and this is the approach I always used, the way to do it is to simply create a 404.html page at root level in the templates folder.
Related
When using HTMX framework with Python Flask, you have to be able to:
serve a request as a HTML fragment if it's done by HTMX (via AJAX)
server a request as a full page if it's done by the user (e.g. entered directly in the browser URL bar)
See Single-page-application with fixed header/footer with HTMX, with browsing URL history or Allow Manual Page Reloading
for more details.
How to do this with the Flask template system?
from flask import Flask, render_template, request
app = Flask("")
#app.route('/pages/<path>')
def main(path):
htmx_request = request.headers.get('HX-Request') is not None
return render_template(path + '.html', fullpage=not htmx_request)
app.run()
What's the standard way to output a full page (based on a parent template pagelayout.html):
{% extends "pagelayout.html" %}
{% block container %}
<button>Click me</button>
{% endblock %}
if fullpage is True, and just a HTML fragment:
<button>Click me</button>
if it is False?
This solution based on that we can use a dynamic variable when extending a base template. So depending on the type or the request, we use the full base template or a minimal base template that returns only our fragment's content.
Lets call our base template for fragments base-fragments.html:
{% block container %}
{% endblock %}
It's just returns the main block's content, nothing else. At the view function we have a new template variable baselayout, that contains the name of the base template depending on the request's type (originating from HTMX or not):
#app.route('/pages/<path>')
def main(path):
htmx_request = request.headers.get('HX-Request') is not None
baselayout = 'base-fragments.html' if htmx_request else 'pagelayout.html'
return render_template(path + '.html', baselayout=baselayout)
And in the page template, we use this baselayout variable at the extends:
{% extends baselayout %}
{% block container %}
<button>Click me</button>
{% endblock %}
As pointed in the section Null-Default Fallback of Jinja documentation, the extends tag can actually come in an if statement:
Jinja supports dynamic inheritance and does not distinguish between parent and child template as long as no extends tag is visited. While this leads to the surprising behavior that everything before the first extends tag including whitespace is printed out instead of being ignored, it can be used for a neat trick.
Usually child templates extend from one template that adds a basic HTML skeleton. However it’s possible to put the extends tag into an if tag to only extend from the layout template if the standalone variable evaluates to false which it does per default if it’s not defined. Additionally a very basic skeleton is added to the file so that if it’s indeed rendered with standalone set to True a very basic HTML skeleton is added:
{% if not standalone %}{% extends 'default.html' %}{% endif -%}
<!DOCTYPE html>
<title>{% block title %}The Page Title{% endblock %}</title>
<link rel="stylesheet" href="style.css" type="text/css">
{% block body %}
<p>This is the page body.</p>
{% endblock %}
Source: https://jinja.palletsprojects.com/en/3.0.x/tricks/#null-default-fallback
So, your requirement could be fulfilled doing:
{% if not fullpage %}{% extends 'pagelayout.html' %}{% endif -%}
{% block container -%}
<button>Click me</button>
{%- endblock %}
I've a base.html file which has vertical and horizontal menu-bar:
Wherever I want to use that I just simply write:
{% extends 'base.html' %}
{% block content %}
//html code
{% endblock content %}
But I don't know how to use the same file base.html from templates directory in djando admin.
I want output like this:
What I Tried:
How to override and extend basic Django admin templates?
How do I correctly extend the django admin/base.html template?
Override Navbar in Django base admin page to be same as the base.html
I tried few other solution just don't want to increase the length of question and base.html file's code just has basic bootstrap, html code for menus.
I am new to Django, little explanation would be highly appreciated!
What you are looking is similar to nav-global.
Try this:
First create a folder in your templates folder as admin and create a html file(base_site.html) in the same folder
Assuming you have separate html file for menu-bars(Let's say the file is nav.html).
Write the below code in base_site.html:
{% extends 'admin/base.html' %}
{% block nav-global %}
{% include 'nav.html' %} #Your navigation html file
{% endblock %}
Unrelated to question: I found a git repo which will give you idea how to customize the django-admin menu.
You can just extend the admin's base template as
{% extends "admin/base.html" %}
For example:
{% extends "admin/base.html" %}
{% block sidebar %}
{{ block.super }}
<div>
<h1>Extra links</h1>
My extra link
</div>
{% endblock %}
Also, make sure that you have added the admin app to the INSTALLED_APPS
INSTALLED_APPS = [
# other apps,
'django.contrib.admin',
# other apps,
]
I had the same issue about a year and a half ago and I found a nice template loader on djangosnippets.org that makes this easy. It allows you to extend a template in a specific app, giving you the ability to create your own admin/index.html that extends the admin/index.html template from the admin app. Like this:
{% extends "admin:admin/index.html" %}
{% block sidebar %}
{{block.super}}
<div>
<h1>Extra links</h1>
My extra link
</div>
{% endblock %}
For my project, I'm searching for articles on google news based on keyword input by the user, I want to display these links obtained from the search on my results page.
this is my result.html
{% extends 'base.html' %}
{% block title %}Result{% endblock %}
{% block content %}
<h3>Reported Url</h3>
<div>Post Content: <br>{{content}}</div>
<h3>News articles related to your query:</h3>
<ul>
{% for key, value in articles.items %}
<li>{{value}}</li>
{% endfor %}
</ul>
<div>
Back to Home Page
</div>
{% endblock %}
But the links do not work and I get the page not found error, since these links are not contained in urls.py.
How can I link these urls correctly?
thank you
You cannot execute python code inside Django templates.
Check out this thread: Numeric for loop in Django templates
Fixed the problem I had to replace "./" in the article to the homepage of the site I was refering to.
I am trying to set up a proper workflow for a personal website.
I am using the Cactus static site generator which makes use of the Django template system.
I know what I want to do, but I am not sure how to do it as the tutorials for Cactus are limited.
This is what my directory structure looks like:
/mysite/pages/
/mysite/templates/
/mysite/mycontent/
/mysite/plugins/
My template, /mysite/pages/menu.html, looks like this:
<p>Welcome to the page!</p>
{% block body %}
{% endblock %}
And one of my page articles, /mysite/pages/testpage.html, looks like this
{% extends "menu.html" %}
{%block body %}
<p> Test Content </p>
{% endblock %}
But what I am trying to do is set this up so that whatever I want to write for Test Content can be written somewhere else and the copied in to the folder. Something like this:
{% extends "menu.html" %}
{%block body %}
{%include "../mysite/mycontent/TestContent.html}
{% endblock %}
Is this something that Django templates needs to manage? Like I said, I am using Cactus which uses Django templates but I have looked around and am not sure what the standard way of doing this is, even though it seems to work with MVC/MVT philosophy.
There is also an option to use Django plugins with Cactus.
Thanks!
I figured out what I was trying to do. I just had to include the html I wanted using the template language.
{% extends "menu.html" %}
{%block body %}
{% include "./file.html" %}
{% endblock %}
How can I use nav-global for navigation and hide the breadcrumbs in the django admin app. I've found ways to do this but they seem hackish and problematic. I'm looking for a clean reliable solution.
Naive Approach that doesn't work:
customize admin/base_site.html
{% extends "admin/base.html" %}
{% load i18n %}
{% block title %}{{ title }} | {% trans 'Django site admin' %}{% endblock %}
{% block branding %}
<h1 id="site-name">{% trans 'Django administration' %}</h1>
{% endblock %}
{% block nav-global %}Some links will go here...{% endblock %}
{% block breadcrumbs %}{% endblock %}
this doesn't work because the templates in django admin like change_list.html that extend base_site.html will define content for breadcrumbs which will override whatever I have set in base_site.html.
solution 1: CSS
Add the following css to admin using the extrastyle block. This works, but the breadcrumbs still get generated and appear in the HTML source. This feels hacky.
.breadcrumbs {
display: none;
}
Solution 2: override base.html
Override base.html and remove the breadcrumbs block. Children will try to define it but it never exists so it never gets rendered. This also seems like a hack. It's also not a good idea to override base.html as each Django release can make many changes to base.html and the admin app could break between releases.
Extend all templates that you want to render an empty breadcrumbs block. Your first attempt (you say doesn't work) will work, just extend the other templates as well. Like change_list.html:
{% extends "admin/change_list.html" %}
{% block breadcrumbs %}
{% endblock %}
change_form.html:
{% extends "admin/change_form.html" %}
{% block breadcrumbs %}
{% endblock %}
The same for:
500.html
app_index.html
change_password.html
delete_confirmation.html
delete_selected_confirmation.html
invalid_setup.html
object_history.html
login.html and index.html have an empty breadcrumb block.
Downside is that the templates need to be applied per app. This means duplicated templates. If you want to do project wide with single templates you end up with other hacks: copying the complete original templates OR let the templates extend /path/to/site-packages/django/contrib/admin/templates/template_name.html.
Use CSS. You can also hide app_label which is 2nd child.
.breadcrumbs>ul li:nth-child(2),
#grp-breadcrumbs>ul li:nth-child(2) {
display:none;
}
To avoid the recursion problem:
Install django-apptemplates
pip install django-apptemplates
Add the template loader to your settings.py. If you are using Django >= 1.8, add it in the TEMPLATES setting (more details in the doc).
You can now override a template by adding app_name: in the extends tag:
{% extends "admin:admin/change_form.html" %}
{% block breadcrumbs %}
{% endblock %}