Insert a document with Flask-PyMongo - python

I have a MongoDB database and I want to use Flask-PyMongo to work with it in my Flask app. How do I add a database and a collection so I can add user documents?
from flask import Flask, render_template, url_for
from flask.ext.pymongo import PyMongo
app = Flask(__name__)
app.config['MONGO_DBNAME'] = 'microblogdb'
app.config['MONGO_URI'] = 'mongodb://briangunsel:password#microblog:27017/microblogdb'
mongo = PyMongo(app, config_prefix='MONGO')
#app.route('/')
def home():
posts = mongo.db.posts.find({})
return render_template('users.html', posts=posts)
app.run(debug=True)
Update:
With only that code above, when I start up the server (python init.py) and I go to load the web page, it loads for about 10 seconds and then gives me this error https://gist.github.com/anonymous/62ca41e98e67b304838d. I am running the database microblogdb in another cmd prompt, and I set the mongo --dbpath to \data\, which is a folder I created in the microblog folder. Through the mongo interpreter, I added a posts collection, it is still giving me the same error.

mongo.db.users returns the users collection on the database you configured. Flask-PyMongo is using the PyMongo driver, which has extensive documentation. PyMongo's tutorial explains how to insert a document. You already have code that fetches the users who have online=True.
app.config['MONGO_URI'] = 'mongodb://username:password#host:port/db_name'
user_id = mongo.db.users.insert_one({'name': 'david'}).inserted_id

Related

Can I use Flask Restful alongside an existing Flask App?

I have been tasked with working on an existing Flask project (Flask with Templates/Jinja2 style monolith application). I have to add new features to this app and I'm also intending to re-design the app so it becomes a more micro-services based architecure (i.e. initially Flask-restful based backend with React based front-end). Can I just use Flask-restful by just wrapping the existing app and start creating the new endpoints using Resource?
from flask import Flask
from flask_restful import Resource, Api
app = Flask(__name__)
api = Api(app)
Are there any specific caveats/gotcha's I need to worry about?
Let's try it and see what happens. We start with a basic Flask app:
from flask import Flask
app = Flask(__name__)
#app.route("/")
def index():
return "This is index\n"
#app.route("/endpoint1")
def endpoint1():
return "This is endpoint1\n"
This works and we can request the / and /endpoint1 endpoints and get the expected response:
$ curl localhost:5000
This is index
$ curl localhost:5000/endpoint1
This is endpoint1
Let's see if we can mash a flask_restful managed endpoint in there without disrupting the existing functionality:
from flask import Flask, make_response
from flask_restful import Resource, Api
app = Flask(__name__)
api = Api(app)
class Widgets(Resource):
def get(self):
return make_response('Yes we have no widgets today\n')
api.add_resource(Widgets, '/widgets')
#app.route("/")
def index():
return "This is index\n"
#app.route("/endpoint1")
def endpoint1():
return "This is endpoint1\n"
Are our original routes still active?
$ curl localhost:5000
This is index
$ curl localhost:5000/endpoint1
This is endpoint1
How about the new one?
$ curl localhost:5000/widgets
Yes we have no widgets today
It looks like the answer is "yes"!

Access flask app context in worker to access database

I am trying to access db.session in a Flask-RQ job to update my database.
The thing is that I am not able to do it as my app context is not known by the worker which is executing jobs.
I am also using Flask Blueprints to structure my application so I am not able to use app context with from app import app.
Below my application structure:
--> app
--> __init__.py
--> jobs.py
--> routes
--> routes.py
config.py
I created a Blueprint for jobs.py but when I trigger my job in routes.py file I have an error when trying to do query with db.session (note that db is imported with from app import db and session with from flask import session).
RuntimeError: No application found. Either work inside a view function or push an application context.
The job is pretty simple:
#rq.job
def try_rq():
print("Starting task")
db.session.query(...)
print("Task completed")
I do not know how to make my worker knowing the application context and so be able to use db.session to update my database.
Note that without database update the job is working fine.

Finding name and details of a database

I am new to Flask.
I have a task to connect a PostgreSQL database to my Flask app and create some API endpoints.
All the details I have on the database are the following:
Database location: postgres://candidate.company.org/company
Username: interview
Password: cake
To connect to the database I did the following:
myproject/myapp.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgres://interview:cake#candidate.company.org/suade'
db = SQLAlchemy(app)
I think it is connected (how can I be sure it is connected?).
My problem is that in the task it is not written what the database contains or what the name of tables are.
How can I find out the name and content of the tables in the database if I do not know anything about it?
Try query something like: db.session.query("1").from_statement("SELECT 1").all()

Flask session don't persist data

I have a Javascript application and a Flask application. When the user send data from Js to Flask, I store it on session and it works fine at a specific route:
#app.route(...)
def user(...):
session['name'] = name
print(session['name']) # Works !
But when I tr to get the values on session from another method / route the session is empty:
#app.route(...)
def current():
print(session.keys(), session.values) # Empty !
I have installed Flask Session and set the config to:
'SECRET_KEY': b'...',
'SESSION_TYPE': 'filesystem', # Memcache, null and redis
'SESSION_PERMANENT': False, # True
And then started the Flask application and it not work. I have also try to set session.modified = True after I add some new value to session and still not work.
I have read lots of threads on Stack Over Flow, Reddit, etc; and nothing worked. Tips please ?
TL;DR, enable CORS and credentials support on the back end, and use credentials in the front end code when issuing requests.
I recently ran into a similar issue where I was developing a front end and a back end in separate apps. I noticed that each time I issued a request from the front end client, it would create a new session for each request, which would rapidly bloat the session storage on the back end and made user tracking difficult if not impossible.
I'm assuming that you're Javascript app and Flask app are running separately (i.e., the javascript is not on a template being served by the Flask app and hence the js requests are coming from a different origin).
Suppose we have a simple app with Flask-Session enabled running on port 5000:
from flask import Flask, session
from flask_session import Session
app = Flask(__name__)
SECRET_KEY = "changeme"
SESSION_TYPE = 'filesystem'
app.config.from_object(__name__)
Session(app)
#app.route('/foo')
def foo():
return session.sid
#app.route('/bar')
def bar():
return session.sid
Now if we run the app if we navigate to either route on a browser(e.g., http://localhost:5000/foo), we would get the same session id. If you open another tab, open the developer tools and issue the following command in the console, you'd get a cors error:
// Using fetch, you can use jquery or axios
fetch("http://localhost:5000/foo").then(response => {
return response.text()
}).then(data => {
console.log(data)
})
You can fix this easily by installing Flask-CORS and wrapping your app in the CORS class:
from flask import Flask, session
from flask_session import Session
from flask_cors import CORS
app = Flask(__name__)
SECRET_KEY = "changeme"
SESSION_TYPE = 'filesystem'
app.config.from_object(__name__)
Session(app)
CORS(app)
#app.route('/foo')
def foo():
return session.sid
#app.route('/bar')
def bar():
return session.sid
Now if you run the javascript fetch function above, it prints out a different session id each time the request is invoked, even for the same route. That's because Flask can't track the session unless you're issuing the requests from the same origin or unless you provide some way for flask to identify the session. You can do this from your JS by allowing credentials to be passed:
fetch("http://localhost:5000/foo",
{ credentials: 'include' }).then(response => {
return response.text()
}).then(data => {
console.log(data)
})
However, you will get another CORS error regarding Access-Control-Allow-Credentials. You can fix this in you're Flask app by import the cross_origin decorator, wrapping your routes in the decorator and passing supports_credentials=True to the decorator. The flask code would look something like this:
from flask import Flask, session
from flask_session import Session
from flask_cors import CORS, cross_origin
app = Flask(__name__)
SECRET_KEY = "changeme"
SESSION_TYPE = 'filesystem'
app.config.from_object(__name__)
Session(app)
CORS(app)
#app.route('/foo')
#cross_origin(supports_credentials=True)
def foo():
return session.sid
#app.route('/bar')
#cross_origin(supports_credentials=True)
def bar():
return session.sid
Now flask can track the session by the requester (in this case, the browser running the Javascript app).
I had the same problem using classic post request in html. The session, which was still storing values in previous route, would empty itself after my post request.
I solved this using:
app.config.update(SESSION_COOKIE_SAMESITE="None", SESSION_COOKIE_SECURE=True)
I am sharing this in case others are facing the same issue.

How to find postgresql uri for SQLALCHEMY config

I am trying to connect my flask app to my prostgreSQL db, and i find this configuration example (below code). I just do not know how to find my postgreSQL URI
app = Flask(__name__)
#how do i know my postgresql URI
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://localhost/pre-registration'
db = SQLAlchemy(app)
From the documentation of SQLAlchemy (http://docs.sqlalchemy.org/en/latest/core/engines.html#database-urls):
The typical form of a database URL is:
dialect+driver://username:password#host:port/database
This means that, if you have a Postgres DB called my_db running on localhost on port 5432, accessed by username user and password pass, your URL will look like:
postgresql://user:pass#localhost:5432/my_db

Categories