Working with two differents Jinja2 environments - flask

I'm making a Flask app. In some views I need to work with LaTeX templates instead of HTML.
It is posibble to create another Jinja2 environment and use the render_template function choosing the environment to use?
I'm using blueprints and I want to assign the templates folder in same way that I use the main Jinja environment.

You can use Jinja's Environment.overlay method to copy Flask's environment settings and then insert your own template loader to find template specific to a given blueprint (even if they share the name of a template elsewhere in the application).
from jinja import ChoiceLoader
new_loader = ...
existing_loader = app.jinja_env.loader
new_environment = app.jinja_env.overlay(
loader=ChoiceLoader([new_loader, existing_loader]),
autoescape=select_autoescape(['html', 'xml'])
)
Here, I define a new template loader and insert it at the front of Jinja's lookup order. This retains all the rest of the Flask environment settings including variables like request and app.
Alternatively, you could wrap Flask's render_template() function and do the same thing. I've seen both approaches successfully deployed in production.

Related

How can I load a module in a Django template with a variable for the module name?

I want to build some very similar apps in Django, but I want them to load different tag/filter modules. For this I want the html templates to be generic. For example, I would like to have something like
{% load specific_tags %}
and then I would like to define the variable specific_tags in a context processor for each app. But Django thinks that it should look for "specific_tags" in the installed apps in settings.py. How can I tell Django/Python to first evaluate the content of the variable from the context processor?
Best regards
Why don't you simply put this values in setting files, this is the way how I am differentiating between dev, test, demo and production environments, and the use one of the solution found here to load that value sin your template:
Can I access constants in settings.py from templates in Django?

How to access app name from within blueprint template?

I've written a common blueprint for a bunch of independent little apps as a python package. Mostly this is just a top-level template and a style sheet to give the apps a unified design. I'd like to display the current app's name in the top-level template, but I have no idea how. It seems that there is no way to get to the app context from within the blueprint that the app registered.
I've tried this:
#blueprint.context_processor
def appinfo():
return { 'appname': flask.current_app.name }
but it only works when the template is rendered by one of the blueprint's view functions but not from the app's.
blueprint.app_context_processor() does the trick.
Using the Blueprint.context_processor decorator implies that the function will be called only for requests handled by the blueprint. Namespaces are great!
If you'd like 'appname' to be available in every template: app and blueprints alike, registering the context processor with Flask.context_processor should satisfy that.
app = Flask(__name__)
#app.context_processor
def appinfo():
return dict(appname=app.name)

Why are we advised to put templates in project/app_name/templates/app_name/?

In the django tutorial, it recommends that an application's templates go in
project/app_name/templates/app_name
which results in them being referred to from views something like this:
class ScenarioDetails(generic.DetailView):
model = Scenario
template_name= "cmmods/scenario.html"
I would like to understand what is behind this recommendation.
I can't see what situation would make it bad to put templates in
project/app_name/templates
and refer to them thusly:
class ScenarioDetails(generic.DetailView):
model = Scenario
template_name= "scenario.html"
What is behind this recommendation?
It avoids name clashes and it explicitly refers to the app where the template is located.
Say your app defines a couple of templates that are very similar. An easy way to achieve this is to use a base template, e.g. 'base.html'. This is quite a common name, and it is quite likely that other apps use the same name. If you put this template in your root template folder, the names clash and both apps get the same template, depending on which one comes first (or last) in your INSTALLED_APPS.
By putting each template in a folder named after your app, you avoid these name clashes. It is also easier to locate the template from just the template name, which is very useful if your app uses templates from other apps.
Say you use the template detail.html in your app2 app. Django will look for this template in all template folders in the order they are found. Now, your installed apps looks like this:
INSTALLED_APPS = (
'app1',
'app2',
)
Django will look for the detail.html file in the following locations, and picks the first one it finds:
/path/to/project/app1/templates/detail.html
/path/to/project/app2/templates/detail.html
Even though app2 expects the template file in app2/templates/, Django will give the template in app1/templates/ if it exists. You get the wrong template because the (relative) names are the same.
Now, if you would put your template in app2/templates/app2/detail.html, you are sure you get the right template.
The reason is that templates need to be kept separate from templates of other Django apps to prevent collision. This is why all templates in Django apps should be saved in a directory called app_name/templates/app_name.
For example, without doing this, two apps with the same template (same filename) would have a problem if they're used together in the same Django project (without additional work, Django wouldn't know which of these home.html files to use):
app1/templates/home.html
app2/templates/home.html
As a result of the convention to include the app name in the templates path, you can safely create and release a Django app and reuse it in other Django projects without fearing that there will be a filename problem.

django - reusing functions in many views

I have a bunch of functions that I created in some views that must be reused in many other views. Do I need to create a class and put those functions in a class? If yes how exactly has to be done in Django and then how do I call and initiate them in the new views?
Django views are just Python functions. You can call other Python functions from them just as you can from any other Python code. Put your functions into a .py file, import it, and invoke the functions.
Of course, it may make sense for other reasons to create a class to hold the functions, but you certainly don't need to in order to call them from views.
The solution would be to create the myfunctions.py file in your app folder and import it in your views. Your views file would look like:
import myfunctions
def my_view(request):
.....
foo = myfunctions.bar()
....
You look to complicated to Django. Django is just another Python application and lives in the Python world. For example you can create file library.py and import this file where is needed (in modules where the function from library is needed). If you need you library's functions to get data from database, just import models in the library.py and use them.
Django doesn't have such a big think as "module". You creating the architecture, you can define what in your case is module. In general this is just simple directory with init.py file inside to be able to import files from there.
Hope that helped.
From my point of view, if you have a lot of functions that are widely used in your project it make sense put all this in some separate application. I create some module named 'contrib' for this purposes. It can avoid some time for maintaining this code in future

How do I create application scope variable django?

How can I create an application scope variable which is loaded when the django app starts, be in memory and accessible by all.
Basically I want to reuse the variable through out the application without reloading it.
Thanks
You could add it to your settings.py file. Or, add it to the __init__.py file inside the app directory.
Are you referring to something like an environment variable? You could load it via init...
__init__.py
import os
os.environ['APP_VAR_WHATEVER'] = 'hello world!'
Python has three levels of namespace — local (specific to the current function or class method), global (specific to the current module), and built-in. That is, Python does not really have project-wide global variables.
If it's a read-only variable you want, you could use settings.py to define the value and import settings from all other modules that want access to the variable.
If it for both reading and writing, I would likely use the database backend I'm already using with Django, instead of a python variable.
If you could provide a more detailed description of what you're trying to achieve, perhaps we could come up with a better suited solution.