Flask host_matching and static files when using multiple top-level domains - python

So I have two domains:
MAIN_DOMAIN = www.example.com
DUTCH_DOMAIN = www.voorbeeld.com
I want to use the dutch domain with Flask-Babel for i18n support.
To make this possible I'm using host_matching like this:
def create_app(config_class=Config):
app = Flask(__name__, host_matching=True,
static_host=MAIN_DOMAIN)
Finally, routing:
#bp.route('/', host=MAIN_DOMAIN)
#bp.route('/', host=DUTCH_DOMAIN)
def index():
return render_template('index.html')
I might want to change the routing part in the future. But for now this works fine.
Now for the problem, when I navigate to the dutch domain everything works, except that I get many 404 error messages because it can't find the static files. If I change the url of the static files to the MAIN_DOMAIN it works fine. Which makes sense since static_host is set to MAIN_DOMAIN.
So I just can't seem to find a solution for this problem. Is there a way to make both domains for static files work? Or how would you solve this?

Ok. So I've figured it out and actually noticed some interesting behaviour.
So when I go to the main domain. url_for works as expected, so if you would do something like this in your templates:
<script src="{{ url_for('static', filename='jquery/dist/jquery.min.js') }}"></script>
The result would be this:
<script src="/static/jquery/dist/jquery.min.js"></script>
However, when I go to the DUTCH_DOMAIN route I get:
<script src="http://www.example.com/static/jquery/dist/jquery.min.js"></script>
So you don't have to manually add _external=True to url_for for you other domains but it all happens automagically. The reason it didn't work before is because of CORS since from the browser point of view you're loading assets from a different domain instead of from the "local" website.
Hope this helps.

Related

Python - 404 error while rendering template using flask

I am new to flask and python and I was trying to use the render template function open an URL. the 404 error keeps showing instead of the HTML that is in the templates folder.
My folder structure is as follows:
coding folder/
main.py
templates/
----profile.html
The code in my main.py file is as follows:
from flask import Flask, render_template
app = Flask(__name__)
#app.route("/profile/<name>")
def profile(name):
return render_template("profile.html", name=name)
if __name__ == "__main__":
app.run()
my profile.html file contains the following code:
<!doctype html>
<title>sambit's page</title>
<h3>Wassup {{ name }} </h3>
I have been scratching my head over this for more than 4 hours. Please Help!!!!
Are you trying to access using /profile/myname/ or /profile/myname ?
Since your route definition doesn't have a trailing slash, Flask will throw a 404 if you access that route with a trailing slash in your browser. Read more here: Doc
Though they look rather similar, they differ in their use of the trailing slash in the URL definition. In the first case, the canonical URL for the projects endpoint has a trailing slash. In that sense, it is similar to a folder on a filesystem. Accessing it without a trailing slash will cause Flask to redirect to the canonical URL with the trailing slash.
In the second case, however, the URL is defined without a trailing slash, rather like the pathname of a file on UNIX-like systems. Accessing the URL with a trailing slash will produce a 404 “Not Found” error.

Angular Variables rendering undefined with Flask/Jinja

For seemingly no reason my angular $scope variable is not rendering in the browser. My whole project has been working just fine until I created this page today. All other pages still work as expected. I've deleted all my code down to just the variable itself with the following code and its still rendering as [undefined].
I'm using python/flask to serve up the application with the jinja templating engine and therefore have changed the interpolation characters for angular so they don't conflict with the same characters in jinja:
var zues = angular.module('zues', []);
zues.config(['$interpolateProvider', function($interpolateProvider) {
$interpolateProvider.startSymbol('{{[');
$interpolateProvider.endSymbol(']}}');
}]);
Controller:
zues.controller('test', ['$scope', '$http', function($scope, $http){
$scope.test123 = "testing123";
}]);
HTML:
<body ng-app="zues" ng-controller="test">
{{[ test123 ]}}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<script src="/static/assets/js/zues.js"></script>
<script src="/static/assets/js/Controllers/test.js"></script>
python/flask route:
from flask import Flask, render_template
import flask
application = Flask(__name__)
#application.route("/test")
def test():
return render_template('test.html')
if __name__ == "__main__":
application.run(host='127.0.0.1', reloader_type='stat', debug=True)
This renders in the browser simply as:
[Undefined]
I would have expected it to render:
testing123
Anything simple that I'm just overlooking?
I figured it out. My interpolation characters that I picked for angular were too closely related to the characters that Jinja uses by default. Jinja was taking {{[ test123 ]}} and interpreting the square brackets as plain text and then trying to find a variable test123 within my python script that didn't exist.
This didn't seem to break on the rest of the project because the angular variables I used in my html templates in the rest of the project were always bound to something else and therefore being watched by the digest loop whereas in this scenario it would only have been interpolated once.
I changed the interpolation characters to be {[{ test123 }]} so that Jinja never catches it and only angular does.
A few quick changes should help.
1) Get rid of the interpolate provider. You won't need this code if you complete 2 & 3 below.
2) Remove the close bracket ] when you close the controller definition
Yours: }]);
Mine: });
3) Add {{ ' before the set of curly braces and after ' }}
example/ {{ '{{someVariable + "" + anotherVariable}}' }}

my hyperlink generated in django doesn't work

So I have the following environment; django 1.8. apache on ubuntu 14 with mod_wsgi and mod x-sendfile enabled.
I have a very simple view to server the files as follows:
def foo(request, filename):
response = HttpResponse()
response['Content-Disposition'] = 'attachment; filename={0}'.format(filename)
response['X-Sendfile'] = "/home/amir/DjV/Files/{0}".format(filename)
return response
and here's my urlconf regarding the view:
url(r'^foo/(.+)/$', foo)
I've written a snippet that generate absolute path to files to be presented in a download list. The generated paths work fine if I enter them in the browser; but if I use them as hyperlinks, when clicked it goes to blank page. For examlple here is one the urls that is generated by the snippet I mentioned:
http://192.168.43.6:8000/foo/uuid.txt
it works fine and I get to download the uuid.txt, but when I put it into django template as follows, it doesn't work:
192.168.43.6:8000/foo/uuid.txt
My question being: why my link works fine when entered manually but not when used as a hyperlink? Could it be because of being a local address? How can I fix it?
You need to specify a protocol inside your template when doing such things:
192.168.43.6:8000/foo/uuid.txt
However, you should not hard code urls in this way in special not if they are handled inside your Django application. Check {% url %} templating whether it could be a benefit for you

How to load static files in python bottle in URL's

I'm working on a python app in Python Bottle. The app works fine if I'm on 1 lvl deep URLs like /dashboard or /rules or /page. However, if I go deeper like /dashboard/overview or /rules/ruleone or /page/test the CSS, JS, fonts and images will fail. :(
The HTML source code still poinsts to /assets/ but if I'm on an URL like /rules/ruleone, the right path should be something like ../assets or ./assets right? The path /assets/ only works on the first level but not on deeper lvls, in other words: bottle doesnt adapt the static file path to the current directory. How do I fix this?
I'm stuck on this problem for days now, I realy hope someone can help me. :(
My code (simplified):
#!/usr/bin/env python
import lib.bottle as bottle
from lib.bottle import route, template, debug, static_file, TEMPLATE_PATH, error, auth_basic, get, post, request, response, run, view, redirect, SimpleTemplate, HTTPError, abort
import os, sys, re
#route('/dashboard')
#view('secure_page')
def show__page_dashboard():
return dict(page = 'Dashboard')
#route('/rules/<rule>')
#view('secure_page')
def show_page_rules_more(rule):
return dict(page = rule)
#route('/assets/<filepath:path>')
def server_static(filepath):
return static_file(filepath, root='/var/myapp/assets')
TEMPLATE_PATH.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "view")))
bottle.debug(True)
from lib.bottledaemon import daemon_run
if __name__ == "__main__":
daemon_run()
So my app runs in daemon mode. The structure is:
lib
bottle.py
bottledaemon.py
assets
css
js
...
view
secure_page.tpl
footer.tpl
header.tpl
...
server.py
I hope someone can help me out on this, thanks in advance guys, I love u! <3
Alright I found the solution for my problem. Bottle offers an URL tag to dynamicly build URLs.
from bottle import url
#route('/dashboard')
#view('secure_page')
def show__page_dashboard():
return dict(page='Dashboard', url=url)
#route('/assets/<filepath:path>', name='assets')
def server_static(filepath):
return static_file(filepath, root='/var/myapp/assets')
This is how I load my CSS/JS/images
<link href="{{ url('assets', filepath='css/style.css') }}" rel="stylesheet" type="text/css"/>
Dynamic menu URL's (in the navigation for example) is done this way:
{{ url('/dashboard') }}
I hope this info will help someone who is strugling with the same problem as I was.
Tested on v0.12 and v0.13dev
I do use:
#route('/css/<filename>')
def stylesheets(filename):
return static_file(filename, root='./static/css/')
and in template use:
<link href="/css/style.css" rel="stylesheet">
can be replicated for all assets items (img, css, and js)

initializr with bottlepy - css not loaded

I'm trying to use a boilerplate I downloaded from Initializr together with bottle.py. I'm obviously doing something wrong since when I simply try to load index.html the site renders without using any of the stylesheets and I get the following errors in the browser console:
Use of getUserData() or setUserData() is deprecated. Use WeakMap or element.dataset instead. requestNotifier.js:52
The stylesheet http://localhost:8080/css/normalize.min.css was not loaded because its MIME type, "text/html", is not "text/css". localhost:8080
The stylesheet http://localhost:8080/css/main.css was not loaded because its MIME type, "text/html", is not "text/css". localhost:8080
SyntaxError: syntax error modernizr-2.6.2-respond-1.1.0.min.js:1
SyntaxError: syntax error plugins.js:1
SyntaxError: syntax error
My app looks like this:
import bottle # Web server
from bottle import run, route, static_file, error, template # import request
#route('/')
def index():
return static_file('index.html', root='./html/')
#route('./css/<filename>')
def server__static(filename):
return static_file(filename, root='./css/')
if __name__ == '__main__':
# To run the server, type-in $ python server.py
bottle.debug(True) # display traceback
run(host='localhost', port=8080, reloader=True)
The stylesheets are called from index.html like so:
<link type="text/css" rel="stylesheet" href="css/normalize.min.css">
<link type="text/css" rel="stylesheet" href="css/main.css">
My basic folder structure is (snipped js folder etc.):
bottle_test.py
- html
index.html
- css
main.css
normalize.min.css
I understand that bottle doesn't serve static files by itself and I did play around with the route to server-static and added, changed and removed the mimetype argument but can't get it to work.
The entire boilerplate sits in the html folder and the app does find index.html. I tried this in Firefox and Chrome. I'm on Win 8.1 and anaconda's python 2.7 if that matters. What am I doing wrong?
Your paths seem wrong. The CSS route shouldn't start with a ., seems it interferes with how Bottle parses it. And your CSS static_file root doesn't properly reflect the css folder placement relative to the working directory.
This should work alright:
#route('/css/<filename>')
def server__static(filename):
return static_file(filename, root='./html/css')

Categories

Resources