How to recreate/reload app when external config/database changes in Flask - flask

I’m making a server to convert Rmarkdown to Dash apps. The idea is parse all params in the rmd file and make corresponding Dash inputs. Then add a submit button which compile the rmd to html somewhere and iframe back. I use an external database to store the info for rmd paths so user can dynamically add files. The problem is when a rmd file changes, the server has to reparse the file and recreate the app and serve at the same url. I don’t have an elegant solution. Right now I’m doing something like this.
server = Flask(__name__)
#server.route(“rmd/path:path”):
def convert_rmd_to_dash(path):
file = get_file_path_from_db(path)
mtime = get_last_modified_time(file)
cached_app, cached_mtime = get_cache(path)
if cached_mtime == mtime:
return cached_app
inputs = parse_file(file)
app = construct_dash_app(inputs)
return app.index()
def construct_dash_app(inputs):
app = dash.Dash(
name,
server=server,
routes_pathname_prefix=’/some_url_user_will_never_use/’ + file_name + time.time())
app.layout = …
…
return app
It works but I get many routing rules under /some_url_user_will_never_use. Directly overwriting rmd/path might be possible but feels hacky based on Stackoveflow’s answer. Is there a better solution? Thanks.

Related

Referencing image files in markdown for flask app

I am trying to create a simple blog app using flask that uses flask_flatpages to fill a jinja2 template using the contents of a markdown file for each post.
app = Flask(__name__)
app.config.from_pyfile('settings.py')
pages = FlatPages(app)
#app.route('/<path>/')
def blog_post(path):
post = pages.get_or_404(path)
return render_template('post.html', post=post)
The issue I'm having is that I'm unable to link an image in the markdown file, for example the following example_post.md file returns a 404 error in the rendered HTML for the image.png file (when accessing e.g. http://localhost:5000/example_post/)
# Heading
Here is an example image.
![png](image.png)
I think this is because accessing the image attempts to find example_post/image.png, due to the route I created, but the image is actually in the same directory as the post.md file (there is no example_post/ directory). The file structure is as follows:
--app.py
--posts/
----example_post.md
----image.png
--templates/
----post.html
Any suggestions for how to correctly reference the image.png file in this case, or how to better structure the app to make this work?
We can use this below as an example to fix your problem.
from flask import send_from_directory
#app.route('<path:filename>')
def serve_static(filename):
root_dir = os.path.dirname(os.getcwd())
return send_from_directory(os.path.join(root_dir, 'md'), filename)
Example :
https://www.programcreek.com/python/example/65747/flask.send_from_directory

running a function to load csv data into the DB via Django

This should be like nobrainer question., but it intrigues me.
I want to load a roster of countries into the database and yes, I know I could easily do it directly by importing the csv either in mysql or postgres, and I could also write the code snippet into the console (very inconvenient) and would work fine, but I wonder how you do it in django. Because, if I have this:
def loadccountries():
with open(uploads/countries.csv) as f:
reader = csv.reader(f)
for row in reader:
_,created = countries.objects.get_or_create(
name = row[0]
)
then, where do I place that code?, in the views? if yes, then, how do I make that function alone run? I cannot see myself creating artificial urls in urls.py and an html page so that I can call the view from the URL etc. Dont vote me down, I am struggling not to go below 23 score.
You could write a custom management command which calls your loadcountries method.
This would allow you run:
manage.py loadcountries

get list of files in a sharepoint directory using python

I have a url for sharepoint directory(intranet) and need an api to return list of files in that directory given the url. how can I do that using python?
Posting in case anyone else comes across this issue of getting files from a SharePoint folder from just the folder path.
This link really helped me do this: https://github.com/vgrem/Office365-REST-Python-Client/issues/98. I found so much info about doing this for HTTP but not in Python so hopefully someone else needs more Python reference.
I am assuming you are all setup with client_id and client_secret with the Sharepoint API. If not you can use this for reference: https://learn.microsoft.com/en-us/sharepoint/dev/solution-guidance/security-apponly-azureacs
I basically wanted to grab the names/relative urls of the files within a folder and then get the most recent file in the folder and put into a dataframe.
I'm sure this isn't the "Pythonic" way to do this but it works which is good enough for me.
!pip install Office365-REST-Python-Client
from office365.runtime.auth.client_credential import ClientCredential
from office365.runtime.client_request_exception import ClientRequestException
from office365.sharepoint.client_context import ClientContext
from office365.sharepoint.files.file import File
import io
import datetime
import pandas as pd
sp_site = 'https://<org>.sharepoint.com/sites/<my_site>/'
relative_url = "/sites/<my_site/Shared Documents/<folder>/<sub_folder>"
client_credentials = ClientCredential(credentials['client_id'], credentials['client_secret'])
ctx = ClientContext(sp_site).with_credentials(client_credentials)
libraryRoot = ctx.web.get_folder_by_server_relative_path(relative_url)
ctx.load(libraryRoot)
ctx.execute_query()
#if you want to get the folders within <sub_folder>
folders = libraryRoot.folders
ctx.load(folders)
ctx.execute_query()
for myfolder in folders:
print("Folder name: {0}".format(myfolder.properties["ServerRelativeUrl"]))
#if you want to get the files in the folder
files = libraryRoot.files
ctx.load(files)
ctx.execute_query()
#create a dataframe of the important file properties for me for each file in the folder
df_files = pd.DataFrame(columns = ['Name', 'ServerRelativeUrl', 'TimeLastModified', 'ModTime'])
for myfile in files:
#use mod_time to get in better date format
mod_time = datetime.datetime.strptime(myfile.properties['TimeLastModified'], '%Y-%m-%dT%H:%M:%SZ')
#create a dict of all of the info to add into dataframe and then append to dataframe
dict = {'Name': myfile.properties['Name'], 'ServerRelativeUrl': myfile.properties['ServerRelativeUrl'], 'TimeLastModified': myfile.properties['TimeLastModified'], 'ModTime': mod_time}
df_files = df_files.append(dict, ignore_index= True )
#print statements if needed
# print("File name: {0}".format(myfile.properties["Name"]))
# print("File link: {0}".format(myfile.properties["ServerRelativeUrl"]))
# print("File last modified: {0}".format(myfile.properties["TimeLastModified"]))
#get index of the most recently modified file and the ServerRelativeUrl associated with that index
newest_index = df_files['ModTime'].idxmax()
newest_file_url = df_files.iloc[newest_index]['ServerRelativeUrl']
# Get Excel File by newest_file_url identified above
response= File.open_binary(ctx, newest_file_url)
# save data to BytesIO stream
bytes_file_obj = io.BytesIO()
bytes_file_obj.write(response.content)
bytes_file_obj.seek(0) # set file object to start
# load Excel file from BytesIO stream
df = pd.read_excel(bytes_file_obj, sheet_name='Sheet1', header= 0)
Here is another helpful link of the file properties you can view: https://learn.microsoft.com/en-us/previous-versions/office/developer/sharepoint-rest-reference/dn450841(v=office.15). Scroll down to file properties section.
Hopefully this is helpful to someone. Again, I am not a pro and most of the time I need things to be a bit more explicit and written out. Maybe others feel that way too.
You need to do 2 things here.
Get a list of files (which can be directories or simple files) in
the directory of your interest.
Loop over each item in this list of files and check if
the item is a file or a directory. For each directory do the same as
step 1 and 2.
You can find more documentation at https://learn.microsoft.com/en-us/sharepoint/dev/sp-add-ins/working-with-folders-and-files-with-rest#working-with-files-attached-to-list-items-by-using-rest
def getFilesList(directoryName):
...
return filesList
# This will tell you if the item is a file or a directory.
def isDirectory(item):
...
return true/false
Hope this helps.
I have a url for sharepoint directory
Assuming you asking about a library, you can use SharePoint's REST API and make a web service call to:
https://yourServer/sites/yourSite/_api/web/lists/getbytitle('Documents')/items?$select=Title
This will return a list of documents at: https://yourServer/sites/yourSite/Documents
See: https://msdn.microsoft.com/en-us/library/office/dn531433.aspx
You will of course need the appropriate permissions / credentials to access that library.
You can not use "server name/sites/Folder name/Subfolder name/_api/web/lists/getbytitle('Documents')/items?$select=Title" as URL in SharePoint REST API.
The URL structure should be like below considering WebSiteURL is the URL of site/subsite containing document library from which you are trying to get files and Documents is the Display name of document library:
WebSiteURL/_api/web/lists/getbytitle('Documents')/items?$select=Title
And if you want to list metadata field values you should add Field names separated by comma in $select.
Quick tip: If you are not sure about the REST API URL formation. Try pasting the URL in Chrome browser (you must be logged in to SharePoint site with appropriate permissions) and see if you get proper result as XML if you are successful then update the REST URL and run the code. This way you will save time of running your python code.

How to Web2py custom download function

I'm developing a simple webapp in web2py and I want to create a link that let's the user download a file. Like this:
<a href="{{=URL('download',args = FILE)}}" download>
However, I want to do this without having to pass the FILE to the user in the page handler. I want to retrieve an ID from the server asynchronously that will correspond to the file I want to download and then pass it to a custom download function like this:
<a href="{{=URL('custom_download',args = FILEID)}}" download>
This way, I will be able to upload files to the server asynchronously, (I already figured out how to do that) and the download link on the page for that file will work right away without having to reload the page.
So, on the server side, I would do something like this:
def custom_download():
download_row = db(db.computers.FILEID == request.args(0)).select()
download_file = download_row.filefield
return download_file
However, I'm not entirely sure what I need to write in order for this to work.
I assumed that your files are stored in uploads folder, then your custom download function will be:
def custom_download():
download_row = db(db.computers.FILEID == request.args(0)).select().first()
download_file = download_row.filefield
# Name of file is table_name.field.XXXXX.ext, so retrieve original file name
org_file_name = db.computers.filefield.retrieve(download_file)[0]
file_header = "attachment; filename=" + org_file_name
response.headers['ContentType'] = "application/octet-stream"
response.headers['Content-Disposition'] = file_header
file_full_path = os.path.join(request.folder, 'uploads', download_file)
fh = open(file_full_path, 'rb')
return response.stream(fh)

Responding with a static file in viewer

I'am developing a django application using Apache+wsgi_mod. I defined a simple viewer returning user's image. But in case the user hasn't any picture I want to render a static standard image (dependent on sex), stored in my static folder. I know I could use static.serve() but django documentation dissuades this. How to serve a static file from a viewer?
UPDATE:
viewer is a method defined in views.py (img below e.g.)
I might want to return HttpResponseRedirect() to my static content. But than I need absolute URL.
I need this because I've got something like that:
def img(request, usr_id):
usr_image = get_usr_image(usr_id)
if usr_image == None:
return respond_with_standard_image()
else:
response = HttpResponse(mimetype='image/jpg')
response.write(usr_image)
return response
and want to respond with a standard user image.
UPDATE2:
I can do something like that:
return HttpResponseRedirect('http://' + request.get_host() + settings.STATIC_URL + 'img/125px-Silver_-_male.png')
but I'm not satisfied.
Django should'nt be involved into rendering images or any other static file. You should put your users images in a custom directory, and serving it directly with your web server.
Rendering a different image if the original file does not exists can easily be achieved with a rewrite rule.