Merge branch '1.0-maintenance'

This commit is contained in:
David Lord 2019-01-06 15:46:33 -08:00
commit ac6746d1be
No known key found for this signature in database
GPG key ID: 7A1C87E3F5BC42A8
11 changed files with 173 additions and 162 deletions

View file

@ -15,13 +15,14 @@ matrix:
include:
- env: TOXENV=docs-html
- env: TOXENV=devel,lowest,codecov
- os: osx
language: generic
env: TOXENV=py3,codecov
cache:
directories:
- $HOME/Library/Caches/Homebrew
- $HOME/Library/Caches/pip
# disabled because before_install is too slow
# - os: osx
# language: generic
# env: TOXENV=py3,codecov
# cache:
# directories:
# - $HOME/Library/Caches/Homebrew
# - $HOME/Library/Caches/pip
allow_failures:
- python: nightly
- python: pypy3.5-6.0

View file

@ -1,4 +1,4 @@
include Makefile CHANGES.rst LICENSE AUTHORS tox.ini
include Makefile CHANGES.rst CONTRIBUTING.rst LICENSE AUTHORS tox.ini
graft artwork
graft tests

View file

@ -301,8 +301,8 @@ The following configuration values are used internally by Flask:
Serialize objects to ASCII-encoded JSON. If this is disabled, the JSON
will be returned as a Unicode string, or encoded as ``UTF-8`` by
``jsonify``. This has security implications when rendering the JSON in
to JavaScript in templates, and should typically remain enabled.
``jsonify``. This has security implications when rendering the JSON into
JavaScript in templates, and should typically remain enabled.
Default: ``True``
@ -553,6 +553,44 @@ To enable such a config you just have to call into
app.config.from_object('configmodule.ProductionConfig')
Note that :meth:`~flask.Config.from_object` does not instantiate the class
object. If you need to instantiate the class, such as to access a property,
then you must do so before calling :meth:`~flask.Config.from_object`::
from configmodule import ProductionConfig
app.config.from_object(ProductionConfig())
# Alternatively, import via string:
from werkzeug.utils import import_string
cfg = import_string('configmodule.ProductionConfig')()
app.config.from_object(cfg)
Instantiating the configutation object allows you to use ``@property`` in
your configuration classes::
class Config(object):
"""Base config, uses staging database server."""
DEBUG = False
TESTING = False
DB_SERVER = '192.168.1.56'
@property
def DATABASE_URI(self): # Note: all caps
return 'mysql://user@{}/foo'.format(self.DB_SERVER)
class ProductionConfig(Config):
"""Uses production database server."""
DB_SERVER = '192.168.19.32'
class DevelopmentConfig(Config):
DB_SERVER = 'localhost'
DEBUG = True
class TestingConfig(Config):
DB_SERVER = 'localhost'
DEBUG = True
DATABASE_URI = 'sqlite:///:memory:'
There are many different ways and it's up to you how you want to manage
your configuration files. However here a list of good recommendations:
@ -636,7 +674,7 @@ root” (the default) to “relative to instance folder” via the
app = Flask(__name__, instance_relative_config=True)
Here is a full example of how to configure Flask to preload the config
from a module and then override the config from a file in the config
from a module and then override the config from a file in the instance
folder if it exists::
app = Flask(__name__, instance_relative_config=True)

View file

@ -34,7 +34,7 @@ Snippet Archives <http://flask.pocoo.org/snippets/>`_.
jquery
errorpages
lazyloading
mongokit
mongoengine
favicon
streaming
deferredcallbacks

View file

@ -105,7 +105,7 @@ example that shows how you would use jQuery and Flask nonetheless::
return render_template('index.html')
As you can see I also added an `index` method here that renders a
template. This template will load jQuery as above and have a little form
template. This template will load jQuery as above and have a little form where
we can add two numbers and a link to trigger the function on the server
side.

View file

@ -0,0 +1,103 @@
MongoDB with MongoEngine
========================
Using a document database like MongoDB is a common alternative to
relational SQL databases. This pattern shows how to use
`MongoEngine`_, a document mapper library, to integrate with MongoDB.
A running MongoDB server and `Flask-MongoEngine`_ are required. ::
pip install flask-mongoengine
.. _MongoEngine: http://mongoengine.org
.. _Flask-MongoEngine: https://flask-mongoengine.readthedocs.io
Configuration
-------------
Basic setup can be done by defining ``MONGODB_SETTINGS`` on
``app.config`` and creating a ``MongoEngine`` instance. ::
from flask import Flask
from flask_mongoengine import MongoEngine
app = Flask(__name__)
app.config['MONGODB_SETTINGS'] = {
"db": "myapp",
}
db = MongoEngine(app)
Mapping Documents
-----------------
To declare a model that represents a Mongo document, create a class that
inherits from ``Document`` and declare each of the fields. ::
import mongoengine as me
class Movie(me.Document):
title = me.StringField(required=True)
year = me.IntField()
rated = me.StringField()
director = me.StringField()
actors = me.ListField()
If the document has nested fields, use ``EmbeddedDocument`` to
defined the fields of the embedded document and
``EmbeddedDocumentField`` to declare it on the parent document. ::
class Imdb(me.EmbeddedDocument):
imdb_id = me.StringField()
rating = me.DecimalField()
votes = me.IntField()
class Movie(me.Document):
...
imdb = me.EmbeddedDocumentField(Imdb)
Creating Data
-------------
Instantiate your document class with keyword arguments for the fields.
You can also assign values to the field attributes after instantiation.
Then call ``doc.save()``. ::
bttf = Movie(title="Back To The Future", year=1985)
bttf.actors = [
"Michael J. Fox",
"Christopher Lloyd"
]
bttf.imdb = Imdb(imdb_id="tt0088763", rating=8.5)
bttf.save()
Queries
-------
Use the class ``objects`` attribute to make queries. A keyword argument
looks for an equal value on the field. ::
bttf = Movies.objects(title="Back To The Future").get_or_404()
Query operators may be used by concatenating them with the field name
using a double-underscore. ``objects``, and queries returned by
calling it, are iterable. ::
some_theron_movie = Movie.objects(actors__in=["Charlize Theron"]).first()
for recents in Movie.objects(year__gte=2017):
print(recents.title)
Documentation
-------------
There are many more ways to define and query documents with MongoEngine.
For more information, check out the `official documentation
<MongoEngine_>`_.
Flask-MongoEngine adds helpful utilities on top of MongoEngine. Check
out their `documentation <Flask-MongoEngine_>`_ as well.

View file

@ -1,144 +1,7 @@
.. mongokit-pattern:
:orphan:
MongoKit in Flask
=================
MongoDB with MongoKit
=====================
Using a document database rather than a full DBMS gets more common these days.
This pattern shows how to use MongoKit, a document mapper library, to
integrate with MongoDB.
This pattern requires a running MongoDB server and the MongoKit library
installed.
There are two very common ways to use MongoKit. I will outline each of them
here:
Declarative
-----------
The default behavior of MongoKit is the declarative one that is based on
common ideas from Django or the SQLAlchemy declarative extension.
Here an example :file:`app.py` module for your application::
from flask import Flask
from mongokit import Connection, Document
# configuration
MONGODB_HOST = 'localhost'
MONGODB_PORT = 27017
# create the little application object
app = Flask(__name__)
app.config.from_object(__name__)
# connect to the database
connection = Connection(app.config['MONGODB_HOST'],
app.config['MONGODB_PORT'])
To define your models, just subclass the `Document` class that is imported
from MongoKit. If you've seen the SQLAlchemy pattern you may wonder why we do
not have a session and even do not define a `init_db` function here. On the
one hand, MongoKit does not have something like a session. This sometimes
makes it more to type but also makes it blazingly fast. On the other hand,
MongoDB is schemaless. This means you can modify the data structure from one
insert query to the next without any problem. MongoKit is just schemaless
too, but implements some validation to ensure data integrity.
Here is an example document (put this also into :file:`app.py`, e.g.)::
from mongokit import ValidationError
def max_length(length):
def validate(value):
if len(value) <= length:
return True
# must have %s in error format string to have mongokit place key in there
raise ValidationError('%s must be at most {} characters long'.format(length))
return validate
class User(Document):
structure = {
'name': unicode,
'email': unicode,
}
validators = {
'name': max_length(50),
'email': max_length(120)
}
use_dot_notation = True
def __repr__(self):
return '<User %r>' % (self.name)
# register the User document with our current connection
connection.register([User])
This example shows you how to define your schema (named structure), a
validator for the maximum character length and uses a special MongoKit feature
called `use_dot_notation`. Per default MongoKit behaves like a python
dictionary but with `use_dot_notation` set to ``True`` you can use your
documents like you use models in nearly any other ORM by using dots to
separate between attributes.
You can insert entries into the database like this:
>>> from yourapplication.database import connection
>>> from yourapplication.models import User
>>> collection = connection['test'].users
>>> user = collection.User()
>>> user['name'] = u'admin'
>>> user['email'] = u'admin@localhost'
>>> user.save()
Note that MongoKit is kinda strict with used column types, you must not use a
common `str` type for either `name` or `email` but unicode.
Querying is simple as well:
>>> list(collection.User.find())
[<User u'admin'>]
>>> collection.User.find_one({'name': u'admin'})
<User u'admin'>
.. _MongoKit: https://github.com/namlook/mongokit
PyMongo Compatibility Layer
---------------------------
If you just want to use PyMongo, you can do that with MongoKit as well. You
may use this process if you need the best performance to get. Note that this
example does not show how to couple it with Flask, see the above MongoKit code
for examples::
from MongoKit import Connection
connection = Connection()
To insert data you can use the `insert` method. We have to get a
collection first, this is somewhat the same as a table in the SQL world.
>>> collection = connection['test'].users
>>> user = {'name': u'admin', 'email': u'admin@localhost'}
>>> collection.insert(user)
MongoKit will automatically commit for us.
To query your database, you use the collection directly:
>>> list(collection.find())
[{u'_id': ObjectId('4c271729e13823182f000000'), u'name': u'admin', u'email': u'admin@localhost'}]
>>> collection.find_one({'name': u'admin'})
{u'_id': ObjectId('4c271729e13823182f000000'), u'name': u'admin', u'email': u'admin@localhost'}
These results are also dict-like objects:
>>> r = collection.find_one({'name': u'admin'})
>>> r['email']
u'admin@localhost'
For more information about MongoKit, head over to the
`website <https://github.com/namlook/mongokit>`_.
MongoKit is no longer maintained. See :doc:`/patterns/mongoengine`
instead.

View file

@ -3,9 +3,7 @@
Larger Applications
===================
For larger applications it's a good idea to use a package instead of a
module. That is quite simple. Imagine a small application looks like
this::
Imagine a simple flask application structure that looks like this::
/yourapplication
yourapplication.py
@ -17,8 +15,10 @@ this::
login.html
...
The :ref:`tutorial <tutorial>` is structured this way, see the
:gh:`example code <examples/tutorial>`.
While this is fine for small applications, for larger applications
it's a good idea to use a package instead of a module.
The :ref:`tutorial <tutorial>` is structured to use the package pattern,
see the :gh:`example code <examples/tutorial>`.
Simple Packages
---------------

View file

@ -127,7 +127,8 @@ Run The Application
Now you can run your application using the ``flask`` command. From the
terminal, tell Flask where to find your application, then run it in
development mode.
development mode. Remember, you should still be in the top-level
``flask-tutorial`` directory, not the ``flaskr`` package.
Development mode shows an interactive debugger whenever a page raises an
exception, and restarts the server whenever you make changes to the

View file

@ -108,6 +108,7 @@ You can observe that the project is now installed with ``pip list``.
Nothing changes from how you've been running your project so far.
``FLASK_APP`` is still set to ``flaskr`` and ``flask run`` still runs
the application.
the application, but you can call it from anywhere, not just the
``flask-tutorial`` directory.
Continue to :doc:`tests`.

View file

@ -156,6 +156,10 @@ class Config(dict):
from yourapplication import default_config
app.config.from_object(default_config)
Nothing is done to the object before loading. If the object is a
class and has ``@property`` attributes, it needs to be
instantiated before being passed to this method.
You should not use this function to load the actual configuration but
rather configuration defaults. The actual config should be loaded
with :meth:`from_pyfile` and ideally from a location not within the