Using Flask to embed a local HTML page [duplicate] - python-3.x

This question already has answers here:
How to serve static files in Flask
(24 answers)
Closed 6 years ago.
So I am using this cool plugin called Folium which creates maps. The map gets created as a .html and every time you update the map it regenerates the html. So in order to display the map and my navbar and other stuff on the same page I think I would need to put map.html inside an iframe cage where it can refresh itself at will.
The map gets created thus:
map1 = folium.Map(location=[45.5, -73.61], width="100%", height="100%")
map1.save('./maps/map.html')
And I have tried iframeing it thus:
<iframe src="/maps/map.html"></iframe>
But I get 404 error
Someone yesterday suggested that I build an endpoint for it like this:
#app.route('/http://127.0.0.1:4995/maps/map')
def show_map():
return flask.send_file('/maps/map.html')
But I keep getting 404 error

You have your route defined incorrectly. As you had it written, you defined the route for http://yourserver/http://127.0.0.1:4995/maps/map when instead what I think you wanted was http://yourserver/maps/map.html. To achieve this, you will want to use the following
#app.route('/maps/map.html')
def show_map():
return flask.send_file('/maps/map.html')
Flask will automatically prepend your server's address (http://127.0.0.1:4995) to the beginning of any route that you define.
Also, in the template for your HTML, I would use url_for to get the URL for the map to avoid changes in your routes requiring changes to your templates.
<iframe src="{{ url_for('show_map') }}"></iframe>

Related

Universal correct links from navigation partial (express.js & handlebars)

this seems like a very stupid question, but I really can't figure out how to do my navigation links properly.
I'm using express.js with handlebars as view engine.
My backend.handlebars has a naviation bar and loads in every sub-page of my backend under "/admin". It looks like this:
<nav>
Dashboard
Add Post
Edit Post
Categories
Static Text
</nav>
Now the correct routes are:
[server-adress]/admin/ for the dashboard
[server-adress]/admin/add for adding posts
[server-adress]/admin/edit for the editing posts
etc.
Now the way I've setup my links sometimes works and sometimes doesn't.
Sometimes every link works correctly when I'm in a sub-route like "admin/add" and want to go to "admin/edit".
Sometimes every link works when I'm under the main "admin/" to every sub-page, but not the other way around.
And sometimes everything works as intended, mostly when I delete the dot in front of the slash and then add it back end, restarting both times.
This obviously is too much of a gamble when deployed. As I don't know the absolute adress due to changing servers, I can't use absolute paths.
How do I go about this correctly?

Rendering a user modified page using PhantomJS

My use case is: a user goes onto a webpage and modifies it by either filling in a form, populating the page with data from the database, or dragging around some draggables on the page. He can then download the page he modified as pdf. I was thinking of using PhantomJS to do the conversion from html to pdf.
I understand the basic functionality of PhantomJS and got the basic example working but in all the examples I've seen, either a local file or a url is passed in. Example:
page.open('./test.html', function () { ... }
How would I render the page that is getting modified by a user using PhantomJS? I have 2 ideas:
Have the url change as the user modifies the page, and simply pass in the url. For example, the url contains the position of a draggable div.
Send the modified html to back-end, save it, and run PhantomJS
Do these solutions make sense? I'm hoping there would be a simpler way.

Link href in a pug template

I am using pug as the view engine of a nodejs application. I have a layout that every other current view extends, that contains a navbar with links to common urls across the app.
For example, a link to the signin url would look like :
a(href='/auth/signin')`
This works fine from the root url ('/'), correctly leads to '/auth/signin'.
Within the '/auth' module which contains the routes for '/auth/signin', '/auth/signup' and '/auth/signout', the behavior is different. Instead, the route is concatenated with the current module's name. So for example, within the '/auth/signin' route, the link is actually a link to '/auth/auth/signin'. Clicking on it naturally leads to a 404, but on that page the link to signin is a link to '/auth/auth/auth/signin'.
And so on and so forth.
I don't fully understand what is going on here and how to prevent it. Is there away to link to my routes in absolute terms in pug without straight up typing the full url (which is unpractical for a variety of reasons), the same way you'd use a route helper in Ruby on Rails ?
Solution from the comments:
If you start your href's with a slash then these are interpreted as absolute url's. Then it does not matter in which folder your pug file is located. Please check that your href's start with / always.

Can I render all zones to an HTML string in a controller method

I'm trying to render the HTML for a content item to a string from within a controller action. Technically I just want to get the "body" part of it without any header/footer stuff. I want to do this so I can get a content item rendering the way I want once, and then display it as a normal orchard page OR by requesting the HTML for the content item via ajax to display it in a div in a JavaScript app. I don't want to have to manually render everything in the JavaScript as that would be duplicating the layout logic I already did. I want to re-use the bulk of the server side rendering so any changes are reflected in my normal orchard page and my JavaScript page. I've been digging into the code and searching everywhere and have gotten close but not all the way there.
I found these:
How to render shape to string?
Using FindView in Orchard
In my controller I have:
var shape = _contentManager.BuildDisplay(contentItem);
Using either of the two methods above, I can render that shape to an HTML string in my controller. All was golden. I was getting the body of that page and using it in JS. Then, I changed a placement file:
<Place Parts_Common_Body="Content:1" />
was changed to:
<Place Parts_Common_Body="/AsideFirst:1" />
The body moved where I wanted it (AsideFirst) in my normal Orchard page but disappeared from the HTML retrieved using the two methods above.
If I look at shape.Content.Items after the BuildDisplay call, I can see the item for the body is no longer there... why is it not rendering all the zones? Or, I guess a more specific question is why is the BuildDisplay method not building the complete shape? Is there a way I can make this work?
I tried a million different things and eventually got this working. Not sure I totally get it yet, but I think the problem had to do with the fact that I was using shape.Content and I'd moved stuff out of the Content zone. And maybe when I was looking at what the BuildDisplay method was returning I was just not looking at some newly created zone that actually did had the stuff I thought was missing. Clearly I need to learn more about zones and shapes... Anyway, I have a new zone called "MainInfo" now that I created in a placement file. I get a MainInfo property on the main shape returned form BuildDisplay and pass shape.MainInfo to the view rendering code and all seems to be working well now.

Reusing Yesod widgets in AJAX results

I'm writing a very simple Yesod message list that uses AJAX to add new list items without reloading the page (both in the case of other users modifying the database, or the client themselves adding an item). This means I have to encode the HTML structure of the message items in both the Halmet template (when the page loads initially) and the Julius template (for when the dynamic addition happens). They look something like this:
In homepage.hamlet:
$if not $ null messages
<ul id=#{listId}>
$forall Entity mid message <- messages
<li id=#{toPathPiece mid}>
<p>#{showMarkdown $ messageText message}
<abbr .timeago title=#{showUTCTime $ messagePosted message}>
And in homepage.julius:
function(message) {
$('##{rawJS listId}').prepend(
$('<li>')
.attr('id', message.id)
.append('<p>' + message.text + '</p>')
.append($('<abbr class=timeago />')
.attr('title', message.posted).timeago())
.slideDown('slow')
);
}
I'd love to be able to unify these two representations somehow. Am I out of luck, or could I somehow abuse widgets into both generating an HTML response, and filling in code in a JavaScript file?
Note: Of course, I understand that the templates would have to work very differently, since the AJAX call is getting its values from a JS object, not from the server. It's a long shot, but I thought I'd see if anyone's thought about this before.
I think it's something of a AJAX best-practice to pick one place to do your template rendering, either on the server or client. Yesod is (currently) oriented toward doing the rendering on the server.
This can still work with AJAX replacement of contents, though. Instead of getting a JSON response from the POST, you should get a text/html response that contains the result of rendering the template on the server with the values that would have been returned via JSON and then replacing the innerHTML of the DOM node that's being updated.
If you want to support both JSON and HTML responses (to support 3rd party applications via API or something) you would have to make the format of the response be a function of the request; either appending ".json" or ".html" to the URL or including a HTTP header that lists the specific document type required by the client.
It would be nice if Yesod provided a 'jwhamlet' template or something that would render the HTML via javascript in order to support client rendering, but I'm not aware of one. That's not to say there isn't one I'm not aware of, though, so keep an eye open for other answers.
If you wanted to make such a thing, you might try tweaking the hamlet quasi-quote code so that instead of expanding the quasi-quotes to an html-generating function, it expanded them to a JSON-generating function and a pre-rendered chunk of text that's a template in mustache-style such that the JSON returned by the function would provide the correct context for the template to be rendered the way you want.

Resources