Flask-Admin (python) - Having trouble overriding templates - python

I am attempting to utilize Flask-Admin for an administrative interface to my web service.
I have it working, but the theme does not match what the rest of my site uses. The documentation here suggests that it is as simple as overriding the master template, but when I do that I end up with circular reference errors.
I have also tried on individual templates by copying the templates from the install directory to my application structure, but I cannot figure out the path they use. It is like it just defaults to the install directory, even if I have templates of the same name local to my flask app. From the docs: "You can override any used template in your Flask application by creating template with same name and relative path in your main templates directory."... yet I am not able to do that. Does it still expect admin/ in front of the templates?
Does anyone have an example? I basically need to override the bootstrap theme used, but some other customization could be nice. I'm new to flask, and python for that matter, so this may be quite simple...

You will still need to place your templates in the admin sub-folder of templates:
yourapp/
app.py
templates/
master.html # <-- This will not override admin/master
admin/
master.html # <-- This one, however, will :-)

Related

What is the best practice in structuring templates in your Django project?

I know there's a lot of questions regarding best practices of how to structure an entire Django project but i cannot find a concrete explanation on how to structure templates for a Django project.
Obviously, I've just started learning Python/Django and i'm quite confused why most of the tutorials/examples i found, the directory name under templates directory is always the same as the applications directory name.
For example:
gazette/
__init__.py
models.py
views.py
static/
...
templates/
gazette/
__base.html
__l_single_col.html
__l_right_sidebar.html
__l_left_sidebar.html
_article_full.html
_article_summary.html
_author_list.html
_author_name.html
_category_list.html
_navigation.html
_tag_list.html
article_detail.html
article_list.html
author_list.html
category_list.html
tag_list.html
this actually came from a blog: https://oncampus.oberlin.edu/webteam/2012/09/architecture-django-templates
In the application structure above, the application gazette/ have templates/ directory under it. In turn, under templates/, there's a single directory called gazette/, which is the same name as the application directory where it's contained. Under this folder are the actual html template files.
Question: Why can't we just directly put all the html template files under templates/ directory?
I would understand the logic of the structure if there are several directories under templates folder. However, i never found a single example from any tutorials in YouTube or blogs that shows a project structure where there are several directories under templates directory. Instead, they have to name their one and only directory (under templates) same as the the application directory.
If you could explain the principle behind it and direct me to any reference/link, i would greatly appreciate it.
Thanks in advance
One alternative for storing templates is to store each app's templates inside the templates directory of the app.
So the project structure would look something like this
Project
app1
templates
app1
template1.html
template2.html
app2
templates
app2
template1.html
This way you can render the template from the view by passing 'app1/templates1.html'
Your Django Project Template at the end of the day is a personal choice, yes there are known templates that optimize your workflow for most projects, but at the end of the day every project is different, for example this is the template i use when i work for someone who expect me to follow the guidelines
Project
app1
app2
..etc
static
app1
images
css
js
app2
...etc
templates
app1
file.html
...etc
app2
..etc
log_files
app1_info.log
app2_info.log
app1_erros.log
..etc
this is because the Django philosophy is based on separation, Django is built around encouraging modularity
when i'm working on personal projects, i like to mix everything because even if use different apps for different things, i'll still have the same style and same templates across most of them.

How do I define custom filters for minimal use of django templates?

I have a python project that I'm using Django templates for to generate C++ source code.
I picked Django because the template language is quite restrictive and has a very large community making it easy for end-use developers to use and get help with.
I'm failing to add custom filters for my project (to translate one set of type names into another) because I have not done the normal django setup.
Instead:
from django.template import Context, Template
import django
if not django.conf.settings.configured : django.conf.settings.configure()
django.setup()
Lets me use Django templates perfectly but not define custom filters.
My custom filter is called ctypes_filters.py and I reference it in the template as
{% load ctypes_filters %}
Running my generation script results in the following error:
django.template.base.TemplateSyntaxError: 'ctypes_filters' is not a valid tag library: Template library ctypes_filters not found, tried
django.templatetags.ctypes_filters
How can I get django to find the filter without setting up a full Django project (database definitions etc)?
I know that other templating solutions are available (and are probably more light-weight) but I'm really keen to use Django's simple and elegant templates.
The location of Django template tags is done by convention rather than a configuration setting (see the code layout section of the template tags docs).
Put the ctypes_filter.py in a templatetags directory in an installed app (I've called it myapp here). Add an empty __init__.py to both the myapp and templatetags directories. The app doesn't need any other files you might commonly find in a Django app, like models.py or views.py.
myapp/
__init__.py
templatetags/
__init__.py
ctypes_filter.py
Then include myapp in your INSTALLED_APPS when configuring your settings.
django.conf.settings.configure(
INSTALLED_APPS=('myapp',),
)

Adding Reference Without Using add_static_view

I'm building an application in Pyramid and utilizing Jinja2 templates and traversal routing. In order to wire my view-callables with the templates I am using, I want to be able to reference my templates using the webapp:templates prefix. As an example:
#view_config(name='about-us', renderer='webapp:templates/pages/about-us.html', context=Root)
def static_pages(context, request):
... //more code
This decouples where the templates live from whats using them. In order to make the above functional, though, I had to put this inside the __init__.py in my webapp root folder:
config.add_static_view(name='templates', path='webapp:templates', cache_max_age=3600)
The add_static_view() causes the webapp/templates folder to be referenced as webapp:template in other configurations. However, it also makes it viewable from a url such as http://0.0.0.0:6543/templates/<some template file>. Is there a way to achieve the former goal without allowing the latter visibility as a static page?
add_static_view() is not supposed to cause the webapp/templates folder to be referenced as webapp:template in other configurations, if it does that it's just due to a weird side-effect.
The package:path syntax works because Pyramid uses pkg_resources API to resolve the paths. Here are some details.
This means that, in your example, webapp should be a python package located somewhere your app can find it.

Custom django admin template for app

I would like to create a custom index.html derived from the admin/index.html individual for each app in my django project.
For instance my folder structure is like:
app1
templates
index.html (different from the global template admin/index.html)
app2
templates
admin
base.html
index.html (global template index.html)
How can I achieve custom admin index.html files for my apps, that are recognized by django? For the moment only the index.html in the global template/admin folder is considered for rendering the index pages in my backend.
I'm using django 1.6
Unfortunately, only certain parts of the Django admin site can be overridden on a per-app basis, as it says in the documentation:
Not every template in contrib/admin/templates/admin may be overridden per app or per model. The following can:
app_index.html
change_form.html
change_list.html
delete_confirmation.html
object_history.html
Remember that the admin interface is itself and app, so it's going to do a single template sweep and load the first set of templates that comes up.
I think your two best bets are either to use multiple admin sites in your project or to add a custom view for specific apps -- the former is probably easier, but will be a problem if you don't want people to have to login separately to control certain things.

Flask - Jinja environment magic in a Blueprint

When inside a jinja template:
How is the string, provided to {%extends xxx_string%} and {% include xxx_string%}, resolved?
Is this relative to actual filesystem, or a generated namespace (such as when using the Flask.url_for function)?
Ultimately, I would like to use relative imports when inside my templates (I don't want to have to update filesystem locations INSIDE each and every template, with respect to the Blueprint). I would like to be able to :
Store the actual Blueprint package and its nested static/template resources under an arbitrary filesystem path. ('/bob/projects/2013_07/marketanalysis')
Within the python Blueprint package, define a separate 'slugname' to reference the blueprint instance and all of its resource. Register this slugname on the application for global references. (without global name collisions or race-conditions)
Have generic view functions that provide 'cookie-cutter' layouts, depending on how the blueprint is being used (headlines, cover, intro, fullstory, citations)
Internally, within the filesystem of the blueprint package, use relative pathnames when resolving extends()/include() inside templates (akin to url_for shortcuts when referencing relative blueprint views).
The idea is that when the blueprint package is bundled with all of its resources, it has no idea where it will be deployed, and may be relocated several times under different slug-names. The python interface should be the same for every "bundle", but the html content, css, javascript, and images/downloads will be unique for each bundle.
I have sharpened the question quite a bit. I think this is as far as it should go on this thread.
Using folders instead of prefixes makes it a bit more clean in my opinion. Example application structure:
yourapplication
|- bp143
|- templates
|- bp143
|- index.jinja
|- quiz.jinja
|- context.jinja
|- templates
|- base.jinja
|- index.jinja
|- bp143
|- context.jinja
With the above structure you can refer to templates as follows:
base.jinja --> comes from the application package
index.jinja --> comes from the application package
bp143/index.jinja --> comes from the blueprint
bp143/context.jinja --> comes from the application package (the app overrides the template of the same name in the blueprint)
Explicitly load templates using... (not tested)
#blueprint.route('/summarize_article')
def summarize():
fd = blueprint.open_resource('/blueprint/relative/pathid/section/introductions.jinja')
relative_ctx['article_intro'] = flask.render_template_string(fd.read(), **context)
fd = blueprint.open_resource('/blueprint/relative/pathid/section/citations.jinja')
relative_ctx['article_citations'] = flask.render_template_string(fd.read(), **context)
fd = blueprint.open_resource('/blueprint/relative/pathid/summarized_layout.jinja')
return flask.render_template_string(fd.read(), **relative_ctx)
Manually load these templates as needed for each view. Im sure this could be cleaned up for multiple views, but I believe this is the intended behavior.
I am not sure if you can {% extend context_kword_key %}, but it should work for embedded includes()/imports().
It seems the most appropriate solution for my "resource bundling" should be handled with Jinja loaders (see Jinja Docs on Loaders). Right away, jinja2.PackageLoader, jinja2.PrefixLoader, and jinja2.DictLoader seem like they could be fun.
The accepted answer for this Similar Thread gives an idea of how Loaders are handled in Flask. For the most part, we can stay out of the default application-level DispatchingJinjaLoader.
By default, I believe a Blueprint will end up with its self.jinja_loader to ...
jinja2.FileSystemLoader(os.path.join(self.root_path,
self.template_folder))
This help us to understand how simple the default resolution algorithm is, and how easily we can extend Blueprint specific functions. A clever combination of Subclassed/Custom Loaders will let us create smarter Loaders, and allow us to sneak in a few magics that help us cheat.
The real power will come from overriding CustomBaseLoader.list_templates() and a quick little ProxyLoader hooked into the application's DispatcherJinjaLoader that will have priority over normal lookups.

Categories