a jinja variable for flask-app root directory - python

I have been developing an app using the very easy-to-pickup Flask system and I have used a jinja template to write out a bunch of links that correspond to pages in Flask that are defined by something like this:
#app.route(/<var1>/<var2>)
...
...
in the test server these links work just fine however when I move from the test server to a server behind a proxy I get a problem where the href links don't take into account the extra directory name inserted by my proxy.
#where a link should read:
server:/myapp/<var1>/<var2>
# it acually puts out:
server:/<var1>/<var2>
my jinja etemplate looks like this but I am wondering if instead of putting a backslash there is a way to put a variable that specifies root directory.
{% block navigation %}
{% for record in db.values() %}
<li>{{record.name}}</li>
{% endfor %}
{% endblock %}
Any help would be greatly appreciated. Thanks Flask team!

Firstly, as #reclosedev said, you can generate URLs using the url_for function (assuming the view function is called myview:
<a href="{{ url_for('myview', var1=db.name, var2=record.name) }}">
Secondly, if you're behind a reverse proxy, wrap the WSGI application with this decorator that updates the request environment so that Flask generates correct URLs.

Maybe you are looking for url_for function?
<li><a href="{{ url_for('view_func_name',
var1=db.name,
var2=record.name) }}">{{record.name}}</a></li>

Related

Django/Wagtail - How to create a conditional in template that checks for url path?

I'm struggling to finding a quick and easy solution to show HTML content based on a conditional that checks if the wagtail page is at root, aka '/'.
According to the Wagtail docs, I can also make this work using original request object from Django:
Additionally request. is available and contains Django’s request
object.
This is essentially what I want to do. I use the page object here from wagtail but it might be better if I used the request object from Django instead. How can I
{% if page.request.path == '/' %}
<div> show something </div>
{% else %}
#show nothing
{% endif %}
How can I structure a conditional to solve what I'm trying to do?
Access request
The request object can be accessed via request and not page.request.
A helpful tip is to add {% debug %} to see ALL the context that is available to the current template while working locally and debugging.
{% if request.path == '/' %}
<div> show something </div>
{% else %}
#show nothing
{% endif %}
More info
Within Wagtail the request object should be available to all templates, however you may need to enable this by following the instructions about Using RequestContext in the Django docs.
Alternatively this Django request in template answer provides a clear example of what to update in your settings file.

Django load script from another app into an html file

I'm having trouble using a script from a file in App1 in a page in app2.
My project structure looks like this:
I want to use the following file in home/static/scripts/scripts.py
Inside an html file in project/templates/project/s3.html
My scripts.py file looks like this:
import boto3
def listS3():
s3 = boto3.resource('s3')
for bucket in s3.buckets.all():
print(bucket.name)
My s3.html file looks like this:
{% include "home/_header.html" %}
{% block content %}
{% load staticfiles %}
<div class="s3">
</div>
{% endblock content %}
To be frank I'm not even sure how to load that script and how to call it afterwards as this is my first project in django.
Do I use:
{% load script.py %}
Or something like that?
How do I later call function listS3 in the html file?
Like this?
{% listS3() %}
? I appreciate your help.
I think you do not understand the basic Model-View-Template pattern structure of Django.
It might be a good idea to re-study the basic design of Django and take a look at the code.
This is Django's Official Tutorial
https://docs.djangoproject.com/en/1.11/intro/tutorial01/
Python script methods can not be called directly from within a Django template. In Django, you need to pass variables, objects, and Methods to be used in the Template in the form of "Context" in "View".
This is Django's official tutorial for that part.
https://docs.djangoproject.com/en/1.11/intro/tutorial03/#write-views-that-actually-do-something

Cannot call service in my index.html file; Django error

I am currently working on implementing multiple themes in my web application using bootswatch. The user can choose what css theme they would like to see on the web application by choosing from a pick-list.
I have written a service, kjTheme, to handle this. Ideally, when a user chooses a new theme (say, "Cyborg") in the front-end, my index file will use the line of code:
<link rel="stylesheet" type="text/css" href="" data-ng-href={{ $kjTheme }}"/>
To reference my service. My service then references the corresponding css file path (i.e. '/libs/bootswatch/cyborg/bootstrap.min.css').
However, I am running into a Template Syntax Error.
Exception Value: Could not parse the remainder: '$kjTheme' from '$kjTheme'
And the exception location points to my django\template\base.py
Any ideas as to what I'm doing wrong, or what I could check to get me on the right path?
Thank you!
Django and AngularJS both use the double brace syntax {{ variable }} you will need to escape the double braces at the Django template level so that Django does not try to render your tag
data-ng-href="{% templatetag openvariable %} $kjTheme {% templatetag closevariable %}"
You need to tell Django not to try to parse the Angular tags. Use {% verbatim %} to do that.

How to get absolute URL with domain and protocol in a Django template? [duplicate]

In Django, when I use:
{{ request.build_absolute_uri }}{% static "img/myimage.jpg" %}
It produces: 'http://myurl.com//static/img/myimage.jpg'. This produces an error.
How can I remove the double slashes?
The STATIC URL is:
STATIC_URL = '/static/'
But I don't think removing the first '/' would be a good idea.
The request object is available within your templates and you can easily access attributes such as request.scheme or request.META.HTTP_HOST to construct your base URL that you can prepend ahead of your static URL to get the full URL.
Final example would look something like this:
<img src="{{request.scheme}}://{{request.META.HTTP_HOST}}{% static 'img/myimage.jpg' %}">
The build_absolute_uri method builds an absolute uri for the current page. That means that if you're on e.g. 'http://myurl.com/login/', the resulted full url would be 'http://myurl.com/login//static/img/myimage.jpg'.
Instead, use request.get_host() (optionally together with request.scheme for the url scheme), or preferably, use the sites framework to set a template variable to the current site domain. The get_host() method has some issues regarding proxies.
The get_host() method will return the current domain without a path appended.
I just made a quick template tag for doing this. Create files /myapp/templatetags/__init__.py and /myapp/templatetags/my_tag_library.py, if you don't have them already, and add the following to my_tag_library.py:
from django import template
from django.templatetags import static
register = template.Library()
class FullStaticNode(static.StaticNode):
def url(self, context):
request = context['request']
return request.build_absolute_uri(super().url(context))
#register.tag('fullstatic')
def do_static(parser, token):
return FullStaticNode.handle_token(parser, token)
Then in your templates, just {% load my_tag_library %} and use e.g. {% fullstatic my_image.jpg %}.
In response to earlier comments wondering why someone would need to do this, my particular use case was that I wanted to put a link to a static file inside of an open graph protocol meta tag, and those links need to be absolute. In development the static files get served locally, but in production they get served remotely, so I couldn't just prepend the host to get the full url.
Is this worth an update (Django 2+)?
This helped me specifically because I was trying to put a query in the link, i.e. the myimage.jpg was actually pulling from the DB. I needed a way to put it in the src, which was to replace 'myimage.jpg' with {{ img_link_field_in_model }}.
<img src="{% get_static_prefix %}img/myimage.jpg">
will produce:
<img src="/static/img/myimage.jpg">
The example of the query is:
<img src="{% get_static_prefix %}img/{{img_link_from_model}}">
Use this for apps:
{{ request.build_absolute_uri|slice:":-1" }}{% static "img/myimage.jpg" %}
Use this generally:
{{ request.scheme }}://{{ request.META.HTTP_HOST }}{% static "img/myimage.jpg" %}
Not entirely sure what you're asking, but since the {% static .. %} is only adding /static/ to the front of your path you specify, you could just do that yourself:
{{ request.build_absolute_uri }}static/img/myimage.jpg
Not very modular, but then again most times you don't need direct access to the full url since it will just append it onto whatever url you're at if you use it as a src for some html object.
build_absolute_uri takes the location as an argument which handles the double slash problem.
Unfortunately you cannot pass arguments via the django template language.
You will need to build a custom template tag or filter which accepts an argument to the build_absolute_uri function.
One of the many reasons I prefer Jinja as I can just do this:
{{ request.build_absolute_uri(static('img/foo.png')) }}

jinja2 set background image

I am trying to set the background image using jinja2. I have managed to serve my file from my dev server and can post the image in the document, but I want it to form a nice background with everything else on top.
As an example, I tried this :
{% extends "layout.html" %}
{% block body %}
{% if current_user.is_authenticated %}
{% if commPageData.background_image %}
<body background="{{'/images/'+commPageData.background_image}}">
{% else %}
<body>
{% endif %}
A thing
</body>
I have a css file and a layout file that gives the default behaviour for a template. How can I have a nice background image which I am serving?
You seem to be trying to tell the front end to use application routing without passing it the right commands. I'm assuming you're using Flask. Really, there are two ways (that I can think of) to slice this bread, and it just depends on you. The first is just using standard html and not embedding python to route the app to look for the file, and looks like:
<body background="/path/to/image.jpg">
But, if you want to take advantage of the framework and the template, then you should use the built in method url_for
It looks something like this:
<body background="{{ url_for('static', filename=commPageData.background_image) }}">
'static' being the directory in the application where this image lives.
Now, I'm not sure where commPageData.background_image is coming from in your app. My code snip assumes it is being served as a value it will recognize if passed back to the logic, if that makes sense, and it needs to be where you tell the url_for method looks for it, even when dynamically generated. If you actually have a specific image you want to render as the background, it needs to be specified appropriately:
<body background="{{ url_for('static', filename='image.jpg') }}">
Of course, has been deprecated in HTML5 and may not render appropriately in many browser. It is much preferred to use CSS instead with
<body style="background:url({{'images/'+commPageData.background_image}});">
or put it directly in your CSS file

Categories