├── docs ├── _themes │ ├── .gitignore │ ├── flask │ │ ├── theme.conf │ │ ├── relations.html │ │ ├── layout.html │ │ └── static │ │ │ ├── small_flask.css │ │ │ └── flasky.css_t │ ├── flask_small │ │ ├── theme.conf │ │ ├── layout.html │ │ └── static │ │ │ └── flasky.css_t │ ├── README │ ├── LICENSE │ └── flask_theme_support.py ├── _static │ └── flask-mongokit.png ├── Makefile ├── make.bat ├── index.rst └── conf.py ├── tests ├── __main__.py ├── test_decorator_registration.py ├── run.py ├── __init__.py └── test_base.py ├── MANIFEST.in ├── .gitignore ├── example ├── templates │ ├── task.html │ ├── base.html │ ├── list.html │ └── new.html ├── static │ └── style.css └── todo.py ├── .travis.yml ├── LICENSE ├── setup.py ├── README.rst └── flask_mongokit.py /docs/_themes/.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *.pyo 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /tests/__main__.py: -------------------------------------------------------------------------------- 1 | from run import run 2 | 3 | if __name__ == '__main__': 4 | run() -------------------------------------------------------------------------------- /docs/_static/flask-mongokit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jarus/flask-mongokit/HEAD/docs/_static/flask-mongokit.png -------------------------------------------------------------------------------- / MANIFEST.in: -------------------------------------------------------------------------------- 1 | include LICENSE *.py 2 | recursive-include docs * 3 | recursive-exclude docs *.pyc 4 | recursive-exclude docs *.pyo 5 | prune docs/_build -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.pyc 3 | *.pyo 4 | env 5 | env* 6 | dist 7 | *.egg 8 | *.egg-info 9 | _build 10 | 11 | Vagrantfile 12 | .vagrant/ 13 | -------------------------------------------------------------------------------- /example/templates/task.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block body %} 3 |

Task: {{ task.title }}

4 | Created: {{ task.creation.strftime('%Y-%m-%d %H:%M') }} 5 |

{{ task.text }}

6 | {% endblock %} -------------------------------------------------------------------------------- /docs/_themes/flask/theme.conf: -------------------------------------------------------------------------------- 1 | [theme] 2 | inherit = basic 3 | stylesheet = flasky.css 4 | pygments_style = flask_theme_support.FlaskyStyle 5 | 6 | [options] 7 | index_logo = '' 8 | index_logo_height = 120px 9 | touch_icon = 10 | -------------------------------------------------------------------------------- /docs/_themes/flask_small/theme.conf: -------------------------------------------------------------------------------- 1 | [theme] 2 | inherit = basic 3 | stylesheet = flasky.css 4 | nosidebar = true 5 | pygments_style = flask_theme_support.FlaskyStyle 6 | 7 | [options] 8 | index_logo = '' 9 | index_logo_height = 120px 10 | github_fork = '' 11 | -------------------------------------------------------------------------------- /example/templates/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Simple ToDo Example 4 | 5 | 6 | 7 |

Simple MongoDB ToDo List

8 | {% block body %}{% endblock %} 9 | 10 | -------------------------------------------------------------------------------- /tests/test_decorator_registration.py: -------------------------------------------------------------------------------- 1 | from flask_mongokit import Document 2 | 3 | def decorator_registration(self): 4 | 5 | @self.db.register 6 | class DecoratorRegistered(Document): 7 | pass 8 | 9 | assert len(self.db.registered_documents) > 0 10 | assert self.db.registered_documents[0] == DecoratorRegistered -------------------------------------------------------------------------------- /example/templates/list.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block body %} 3 |

All Items

4 | 9 | Add new Task 10 | {% endblock %} -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - "2.7" 4 | - "2.6" 5 | env: 6 | - FLASK=0.10.1 7 | - FLASK=0.9 8 | - FLASK=0.8.1 9 | services: mongodb 10 | install: 11 | - pip install coverage --use-mirrors 12 | - pip install flask==$FLASK --use-mirrors 13 | - pip install -e . --use-mirrors 14 | script: 15 | - python tests/run.py 16 | notifications: 17 | email: 18 | - christoph.heer@googlemail.com -------------------------------------------------------------------------------- /example/templates/new.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block body %} 3 |

New Todo Task

4 |
5 |

6 | Title: 7 | 8 |

Text: 9 |

10 |

11 | 12 | Back to list 13 |

14 | {% endblock %} -------------------------------------------------------------------------------- /docs/_themes/flask/relations.html: -------------------------------------------------------------------------------- 1 |

Related Topics

2 | 20 | -------------------------------------------------------------------------------- /docs/_themes/flask_small/layout.html: -------------------------------------------------------------------------------- 1 | {% extends "basic/layout.html" %} 2 | {% block header %} 3 | {{ super() }} 4 | {% if pagename == 'index' %} 5 |
6 | {% endif %} 7 | {% endblock %} 8 | {% block footer %} 9 | {% if pagename == 'index' %} 10 |
11 | {% endif %} 12 | {% endblock %} 13 | {# do not display relbars #} 14 | {% block relbar1 %}{% endblock %} 15 | {% block relbar2 %} 16 | {% if theme_github_fork %} 17 | Fork me on GitHub 19 | {% endif %} 20 | {% endblock %} 21 | {% block sidebar1 %}{% endblock %} 22 | {% block sidebar2 %}{% endblock %} 23 | -------------------------------------------------------------------------------- /tests/run.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import unittest 3 | 4 | try: 5 | from coverage import coverage 6 | coverage_available = True 7 | except ImportError: 8 | coverage_available = False 9 | 10 | 11 | def run(): 12 | if coverage_available: 13 | cov = coverage(source=['flask_mongokit']) 14 | cov.start() 15 | 16 | from tests import suite 17 | result = unittest.TextTestRunner(verbosity=2).run(suite()) 18 | if not result.wasSuccessful(): 19 | sys.exit(1) 20 | 21 | if coverage_available: 22 | cov.stop() 23 | 24 | print "\nCode Coverage" 25 | cov.report() 26 | cov.html_report(directory='cover') 27 | else: 28 | print("\nTipp:\n\tUse 'pip install coverage' to get great code " 29 | "coverage stats") 30 | 31 | if __name__ == '__main__': 32 | run() 33 | -------------------------------------------------------------------------------- /docs/_themes/flask/layout.html: -------------------------------------------------------------------------------- 1 | {%- extends "basic/layout.html" %} 2 | {%- block extrahead %} 3 | {{ super() }} 4 | {% if theme_touch_icon %} 5 | 6 | {% endif %} 7 | 9 | {% endblock %} 10 | {%- block relbar2 %}{% endblock %} 11 | {% block header %} 12 | {{ super() }} 13 | {% if pagename == 'index' %} 14 |
15 | {% endif %} 16 | {% endblock %} 17 | {%- block footer %} 18 | 22 | {% if pagename == 'index' %} 23 |
24 | {% endif %} 25 | {%- endblock %} 26 | -------------------------------------------------------------------------------- /example/static/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | max-width: 480px; 3 | padding: 0 10px; 4 | margin: 0 auto; 5 | font: 1em/1.4 Calibri, sans-serif; 6 | color: #222; 7 | background: #fff; 8 | } 9 | 10 | h1 { 11 | margin: 0.25em 0 0.5em; 12 | font-size: 3.5em; 13 | font-weight: bold; 14 | text-decoration: none; 15 | color: #6EAD1A; 16 | } 17 | 18 | h2 { 19 | margin: 1.25em 0 0.75em; 20 | font-size: 1.5em; 21 | text-decoration: none; 22 | } 23 | 24 | a { 25 | font-weight:bold; 26 | text-decoration: none; 27 | color: #6EAD1A; 28 | } 29 | 30 | a:focus { 31 | outline: thin dotted; 32 | } 33 | 34 | a:hover, 35 | a:active { 36 | outline: 0; 37 | } 38 | 39 | a:hover, 40 | a:focus, 41 | a:active { 42 | text-decoration: underline; 43 | color: #6EAD1A; 44 | } 45 | 46 | strong { 47 | font-weight: bold; 48 | } 49 | 50 | ul { 51 | list-style: square; 52 | padding: 0; 53 | margin: 1.4em 0; 54 | } 55 | 56 | li { 57 | margin: 0.35em 0; 58 | } 59 | 60 | p { 61 | margin: 0 0 1em; 62 | } -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import unittest 3 | from flask import Flask 4 | 5 | from test_base import * 6 | 7 | if sys.version_info > (2, 6): 8 | from test_decorator_registration import decorator_registration 9 | setattr(TestCaseContextIndependent, 'test_decorator_registration', 10 | decorator_registration) 11 | 12 | def suite(): 13 | suite = unittest.TestSuite() 14 | suite.addTest(unittest.makeSuite(TestCaseContextIndependent)) 15 | suite.addTest(unittest.makeSuite(TestCaseInitAppWithRequestContext)) 16 | suite.addTest(unittest.makeSuite(TestCaseWithRequestContext)) 17 | suite.addTest(unittest.makeSuite(TestCaseWithRequestContextAuth)) 18 | suite.addTest(unittest.makeSuite(TestCaseMultipleAppsWithRequestContext)) 19 | if hasattr(Flask, "app_context"): 20 | suite.addTest(unittest.makeSuite(TestCaseInitAppWithAppContext)) 21 | suite.addTest(unittest.makeSuite(TestCaseWithAppContext)) 22 | suite.addTest(unittest.makeSuite(TestCaseWithAppContextAuth)) 23 | suite.addTest(unittest.makeSuite(TestCaseMultipleAppsWithAppContext)) 24 | return suite 25 | 26 | -------------------------------------------------------------------------------- /docs/_themes/README: -------------------------------------------------------------------------------- 1 | Flask Sphinx Styles 2 | =================== 3 | 4 | This repository contains sphinx styles for Flask and Flask related 5 | projects. To use this style in your Sphinx documentation, follow 6 | this guide: 7 | 8 | 1. put this folder as _themes into your docs folder. Alternatively 9 | you can also use git submodules to check out the contents there. 10 | 2. add this to your conf.py: 11 | 12 | sys.path.append(os.path.abspath('_themes')) 13 | html_theme_path = ['_themes'] 14 | html_theme = 'flask' 15 | 16 | The following themes exist: 17 | 18 | - 'flask' - the standard flask documentation theme for large 19 | projects 20 | - 'flask_small' - small one-page theme. Intended to be used by 21 | very small addon libraries for flask. 22 | 23 | The following options exist for the flask_small theme: 24 | 25 | [options] 26 | index_logo = '' filename of a picture in _static 27 | to be used as replacement for the 28 | h1 in the index.rst file. 29 | index_logo_height = 120px height of the index logo 30 | github_fork = '' repository name on github for the 31 | "fork me" badge 32 | -------------------------------------------------------------------------------- /docs/_themes/flask/static/small_flask.css: -------------------------------------------------------------------------------- 1 | /* 2 | * small_flask.css_t 3 | * ~~~~~~~~~~~~~~~~~ 4 | * 5 | * :copyright: Copyright 2010 by Armin Ronacher. 6 | * :license: Flask Design License, see LICENSE for details. 7 | */ 8 | 9 | body { 10 | margin: 0; 11 | padding: 20px 30px; 12 | } 13 | 14 | div.documentwrapper { 15 | float: none; 16 | background: white; 17 | } 18 | 19 | div.sphinxsidebar { 20 | display: block; 21 | float: none; 22 | width: 102.5%; 23 | margin: 50px -30px -20px -30px; 24 | padding: 10px 20px; 25 | background: #333; 26 | color: white; 27 | } 28 | 29 | div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p, 30 | div.sphinxsidebar h3 a { 31 | color: white; 32 | } 33 | 34 | div.sphinxsidebar a { 35 | color: #aaa; 36 | } 37 | 38 | div.sphinxsidebar p.logo { 39 | display: none; 40 | } 41 | 42 | div.document { 43 | width: 100%; 44 | margin: 0; 45 | } 46 | 47 | div.related { 48 | display: block; 49 | margin: 0; 50 | padding: 10px 0 20px 0; 51 | } 52 | 53 | div.related ul, 54 | div.related ul li { 55 | margin: 0; 56 | padding: 0; 57 | } 58 | 59 | div.footer { 60 | display: none; 61 | } 62 | 63 | div.bodywrapper { 64 | margin: 0; 65 | } 66 | 67 | div.body { 68 | min-height: 0; 69 | padding: 0; 70 | } 71 | -------------------------------------------------------------------------------- /example/todo.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | 3 | from flask import Flask, request, render_template, redirect, url_for 4 | from flask.ext.mongokit import MongoKit, Document 5 | 6 | app = Flask(__name__) 7 | 8 | 9 | class Task(Document): 10 | __collection__ = 'tasks' 11 | structure = { 12 | 'title': unicode, 13 | 'text': unicode, 14 | 'creation': datetime, 15 | } 16 | required_fields = ['title', 'creation'] 17 | default_values = {'creation': datetime.utcnow()} 18 | use_dot_notation = True 19 | 20 | db = MongoKit(app) 21 | db.register([Task]) 22 | 23 | 24 | @app.route('/') 25 | def show_all(): 26 | tasks = db.Task.find() 27 | return render_template('list.html', tasks=tasks) 28 | 29 | 30 | @app.route('/') 31 | def show_task(task_id): 32 | task = db.Task.get_from_id(task_id) 33 | return render_template('task.html', task=task) 34 | 35 | 36 | @app.route('/new', methods=["GET", "POST"]) 37 | def new_task(): 38 | if request.method == 'POST': 39 | task = db.Task() 40 | task.title = request.form['title'] 41 | task.text = request.form['text'] 42 | task.save() 43 | return redirect(url_for('show_all')) 44 | return render_template('new.html') 45 | 46 | if __name__ == '__main__': 47 | app.run(debug=True) 48 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011 by Christoph Heer 2 | 3 | Some rights reserved. 4 | 5 | Redistribution and use in source and binary forms of the software as well 6 | as documentation, with or without modification, are permitted provided 7 | that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above 13 | copyright notice, this list of conditions and the following 14 | disclaimer in the documentation and/or other materials provided 15 | with the distribution. 16 | 17 | * The names of the contributors may not be used to endorse or 18 | promote products derived from this software without specific 19 | prior written permission. 20 | 21 | THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE COPYRIGHT HOLDERS AND 22 | CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 23 | NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 25 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 26 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 28 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 29 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 30 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 | SOFTWARE AND DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 32 | DAMAGE. -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | """ 2 | Flask-MongoKit 3 | -------------- 4 | 5 | Flask-MongoKit simplifies to use MongoKit, a powerful MongoDB ORM in Flask 6 | applications. 7 | 8 | Links 9 | ````` 10 | 11 | * `documentation `_ 12 | * `development version `_ 13 | * `MongoKit `_ 14 | * `Flask `_ 15 | 16 | """ 17 | import sys 18 | from setuptools import setup 19 | 20 | install_requires = [ 21 | "Flask", 22 | "MongoKit" 23 | ] 24 | 25 | if sys.version_info < (2, 6): 26 | install_requires.append('simplejson') 27 | 28 | setup( 29 | name='Flask-MongoKit', 30 | version='0.6', 31 | url='http://github.com/jarus/flask-mongokit', 32 | license='BSD', 33 | author='Christoph Heer', 34 | author_email='Christoph.Heer@googlemail.com', 35 | description='A Flask extension simplifies to use MongoKit', 36 | long_description=__doc__, 37 | py_modules=['flask_mongokit'], 38 | zip_safe=False, 39 | platforms='any', 40 | install_requires=install_requires, 41 | test_suite='tests.suite', 42 | classifiers=[ 43 | 'Development Status :: 4 - Beta', 44 | 'Environment :: Web Environment', 45 | 'Intended Audience :: Developers', 46 | 'License :: OSI Approved :: BSD License', 47 | 'Operating System :: OS Independent', 48 | 'Programming Language :: Python', 49 | 'Topic :: Internet :: WWW/HTTP :: Dynamic Content', 50 | 'Topic :: Software Development :: Libraries :: Python Modules' 51 | ] 52 | ) 53 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | Flask-MongoKit 2 | ============== 3 | 4 | .. image:: https://secure.travis-ci.org/jarus/flask-mongokit.png 5 | :target: http://travis-ci.org/jarus/flask-mongokit 6 | 7 | Flask-MongoKit simplifies to use `MongoKit`_, a powerful `MongoDB`_ ORM 8 | in Flask applications. 9 | 10 | .. _MongoKit: http://namlook.github.com/mongokit/ 11 | .. _MongoDB: http://www.mongodb.org/ 12 | .. _here: http://bitbucket.org/Jarus/flask-mongokit/ 13 | 14 | Installation 15 | ------------ 16 | The installation is thanks to the Python Package Index and `pip`_ really simple. 17 | 18 | :: 19 | 20 | $ pip install Flask-MongoKit 21 | 22 | If you only can use `easy_install` than use 23 | 24 | :: 25 | 26 | $ easy_install Flask-MongoKit 27 | 28 | .. _pip: http://pip.openplans.org/ 29 | 30 | Flask-MongoKit requires to run some packages (they will be installed automatically if they not already installed): 31 | 32 | * Flask 33 | * MongoKit 34 | * pymongo 35 | 36 | Changelog 37 | ========= 38 | 39 | * **0.6 (08.07.2012)** 40 | 41 | * Use the new app context and again the old request context. 42 | * The MongoKit object is now subscriptable and support the typical syntax to 43 | get a collection.:: 44 | 45 | db['my_collection'].insert({'x': 5}) 46 | 47 | * Restructured and improved test suite. 48 | * Sounds crazy but improved python2.5 support. 49 | 50 | * **0.5 (02.07.2012)** 51 | 52 | * You don't need a request context anymore for the mongodb connection. 53 | (A bad decision ... look in 0.6) 54 | 55 | * **0.4 (23.02.2012)** 56 | 57 | * Support new import system of flask. Use now:: 58 | 59 | from flask.ext.mongokit import Mongokit 60 | -------------------------------------------------------------------------------- /docs/_themes/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010 by Armin Ronacher. 2 | 3 | Some rights reserved. 4 | 5 | Redistribution and use in source and binary forms of the theme, with or 6 | without modification, are permitted provided that the following conditions 7 | are met: 8 | 9 | * Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above 13 | copyright notice, this list of conditions and the following 14 | disclaimer in the documentation and/or other materials provided 15 | with the distribution. 16 | 17 | * The names of the contributors may not be used to endorse or 18 | promote products derived from this software without specific 19 | prior written permission. 20 | 21 | We kindly ask you to only use these themes in an unmodified manner just 22 | for Flask and Flask-related products, not for unrelated projects. If you 23 | like the visual style and want to use it for your own projects, please 24 | consider making some larger changes to the themes (such as changing 25 | font faces, sizes, colors or margins). 26 | 27 | THIS THEME IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 28 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 31 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 | ARISING IN ANY WAY OUT OF THE USE OF THIS THEME, EVEN IF ADVISED OF THE 37 | POSSIBILITY OF SUCH DAMAGE. 38 | -------------------------------------------------------------------------------- /docs/_themes/flask_theme_support.py: -------------------------------------------------------------------------------- 1 | # flasky extensions. flasky pygments style based on tango style 2 | from pygments.style import Style 3 | from pygments.token import Keyword, Name, Comment, String, Error, \ 4 | Number, Operator, Generic, Whitespace, Punctuation, Other, Literal 5 | 6 | 7 | class FlaskyStyle(Style): 8 | background_color = "#f8f8f8" 9 | default_style = "" 10 | 11 | styles = { 12 | # No corresponding class for the following: 13 | #Text: "", # class: '' 14 | Whitespace: "underline #f8f8f8", # class: 'w' 15 | Error: "#a40000 border:#ef2929", # class: 'err' 16 | Other: "#000000", # class 'x' 17 | 18 | Comment: "italic #8f5902", # class: 'c' 19 | Comment.Preproc: "noitalic", # class: 'cp' 20 | 21 | Keyword: "bold #004461", # class: 'k' 22 | Keyword.Constant: "bold #004461", # class: 'kc' 23 | Keyword.Declaration: "bold #004461", # class: 'kd' 24 | Keyword.Namespace: "bold #004461", # class: 'kn' 25 | Keyword.Pseudo: "bold #004461", # class: 'kp' 26 | Keyword.Reserved: "bold #004461", # class: 'kr' 27 | Keyword.Type: "bold #004461", # class: 'kt' 28 | 29 | Operator: "#582800", # class: 'o' 30 | Operator.Word: "bold #004461", # class: 'ow' - like keywords 31 | 32 | Punctuation: "bold #000000", # class: 'p' 33 | 34 | # because special names such as Name.Class, Name.Function, etc. 35 | # are not recognized as such later in the parsing, we choose them 36 | # to look the same as ordinary variables. 37 | Name: "#000000", # class: 'n' 38 | Name.Attribute: "#c4a000", # class: 'na' - to be revised 39 | Name.Builtin: "#004461", # class: 'nb' 40 | Name.Builtin.Pseudo: "#3465a4", # class: 'bp' 41 | Name.Class: "#000000", # class: 'nc' - to be revised 42 | Name.Constant: "#000000", # class: 'no' - to be revised 43 | Name.Decorator: "#888", # class: 'nd' - to be revised 44 | Name.Entity: "#ce5c00", # class: 'ni' 45 | Name.Exception: "bold #cc0000", # class: 'ne' 46 | Name.Function: "#000000", # class: 'nf' 47 | Name.Property: "#000000", # class: 'py' 48 | Name.Label: "#f57900", # class: 'nl' 49 | Name.Namespace: "#000000", # class: 'nn' - to be revised 50 | Name.Other: "#000000", # class: 'nx' 51 | Name.Tag: "bold #004461", # class: 'nt' - like a keyword 52 | Name.Variable: "#000000", # class: 'nv' - to be revised 53 | Name.Variable.Class: "#000000", # class: 'vc' - to be revised 54 | Name.Variable.Global: "#000000", # class: 'vg' - to be revised 55 | Name.Variable.Instance: "#000000", # class: 'vi' - to be revised 56 | 57 | Number: "#990000", # class: 'm' 58 | 59 | Literal: "#000000", # class: 'l' 60 | Literal.Date: "#000000", # class: 'ld' 61 | 62 | String: "#4e9a06", # class: 's' 63 | String.Backtick: "#4e9a06", # class: 'sb' 64 | String.Char: "#4e9a06", # class: 'sc' 65 | String.Doc: "italic #8f5902", # class: 'sd' - like a comment 66 | String.Double: "#4e9a06", # class: 's2' 67 | String.Escape: "#4e9a06", # class: 'se' 68 | String.Heredoc: "#4e9a06", # class: 'sh' 69 | String.Interpol: "#4e9a06", # class: 'si' 70 | String.Other: "#4e9a06", # class: 'sx' 71 | String.Regex: "#4e9a06", # class: 'sr' 72 | String.Single: "#4e9a06", # class: 's1' 73 | String.Symbol: "#4e9a06", # class: 'ss' 74 | 75 | Generic: "#000000", # class: 'g' 76 | Generic.Deleted: "#a40000", # class: 'gd' 77 | Generic.Emph: "italic #000000", # class: 'ge' 78 | Generic.Error: "#ef2929", # class: 'gr' 79 | Generic.Heading: "bold #000080", # class: 'gh' 80 | Generic.Inserted: "#00A000", # class: 'gi' 81 | Generic.Output: "#888", # class: 'go' 82 | Generic.Prompt: "#745334", # class: 'gp' 83 | Generic.Strong: "bold #000000", # class: 'gs' 84 | Generic.Subheading: "bold #800080", # class: 'gu' 85 | Generic.Traceback: "bold #a40000", # class: 'gt' 86 | } 87 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = _build 9 | 10 | # Internal variables. 11 | PAPEROPT_a4 = -D latex_paper_size=a4 12 | PAPEROPT_letter = -D latex_paper_size=letter 13 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 14 | 15 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest 16 | 17 | help: 18 | @echo "Please use \`make ' where is one of" 19 | @echo " html to make standalone HTML files" 20 | @echo " dirhtml to make HTML files named index.html in directories" 21 | @echo " singlehtml to make a single large HTML file" 22 | @echo " pickle to make pickle files" 23 | @echo " json to make JSON files" 24 | @echo " htmlhelp to make HTML files and a HTML help project" 25 | @echo " qthelp to make HTML files and a qthelp project" 26 | @echo " devhelp to make HTML files and a Devhelp project" 27 | @echo " epub to make an epub" 28 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 29 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 30 | @echo " text to make text files" 31 | @echo " man to make manual pages" 32 | @echo " changes to make an overview of all changed/added/deprecated items" 33 | @echo " linkcheck to check all external links for integrity" 34 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 35 | 36 | clean: 37 | -rm -rf $(BUILDDIR)/* 38 | 39 | html: 40 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 41 | @echo 42 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 43 | 44 | dirhtml: 45 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 46 | @echo 47 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 48 | 49 | singlehtml: 50 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 51 | @echo 52 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 53 | 54 | pickle: 55 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 56 | @echo 57 | @echo "Build finished; now you can process the pickle files." 58 | 59 | json: 60 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 61 | @echo 62 | @echo "Build finished; now you can process the JSON files." 63 | 64 | htmlhelp: 65 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 66 | @echo 67 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 68 | ".hhp project file in $(BUILDDIR)/htmlhelp." 69 | 70 | qthelp: 71 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 72 | @echo 73 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 74 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 75 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Flask-MongoKit.qhcp" 76 | @echo "To view the help file:" 77 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Flask-MongoKit.qhc" 78 | 79 | devhelp: 80 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 81 | @echo 82 | @echo "Build finished." 83 | @echo "To view the help file:" 84 | @echo "# mkdir -p $$HOME/.local/share/devhelp/Flask-MongoKit" 85 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Flask-MongoKit" 86 | @echo "# devhelp" 87 | 88 | epub: 89 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 90 | @echo 91 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 92 | 93 | latex: 94 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 95 | @echo 96 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 97 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 98 | "(use \`make latexpdf' here to do that automatically)." 99 | 100 | latexpdf: 101 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 102 | @echo "Running LaTeX files through pdflatex..." 103 | make -C $(BUILDDIR)/latex all-pdf 104 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 105 | 106 | text: 107 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 108 | @echo 109 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 110 | 111 | man: 112 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 113 | @echo 114 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 115 | 116 | changes: 117 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 118 | @echo 119 | @echo "The overview file is in $(BUILDDIR)/changes." 120 | 121 | linkcheck: 122 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 123 | @echo 124 | @echo "Link check complete; look for any errors in the above output " \ 125 | "or in $(BUILDDIR)/linkcheck/output.txt." 126 | 127 | doctest: 128 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 129 | @echo "Testing of doctests in the sources finished, look at the " \ 130 | "results in $(BUILDDIR)/doctest/output.txt." 131 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | REM Command file for Sphinx documentation 4 | 5 | if "%SPHINXBUILD%" == "" ( 6 | set SPHINXBUILD=sphinx-build 7 | ) 8 | set BUILDDIR=_build 9 | set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . 10 | if NOT "%PAPER%" == "" ( 11 | set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% 12 | ) 13 | 14 | if "%1" == "" goto help 15 | 16 | if "%1" == "help" ( 17 | :help 18 | echo.Please use `make ^` where ^ is one of 19 | echo. html to make standalone HTML files 20 | echo. dirhtml to make HTML files named index.html in directories 21 | echo. singlehtml to make a single large HTML file 22 | echo. pickle to make pickle files 23 | echo. json to make JSON files 24 | echo. htmlhelp to make HTML files and a HTML help project 25 | echo. qthelp to make HTML files and a qthelp project 26 | echo. devhelp to make HTML files and a Devhelp project 27 | echo. epub to make an epub 28 | echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter 29 | echo. text to make text files 30 | echo. man to make manual pages 31 | echo. changes to make an overview over all changed/added/deprecated items 32 | echo. linkcheck to check all external links for integrity 33 | echo. doctest to run all doctests embedded in the documentation if enabled 34 | goto end 35 | ) 36 | 37 | if "%1" == "clean" ( 38 | for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i 39 | del /q /s %BUILDDIR%\* 40 | goto end 41 | ) 42 | 43 | if "%1" == "html" ( 44 | %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html 45 | if errorlevel 1 exit /b 1 46 | echo. 47 | echo.Build finished. The HTML pages are in %BUILDDIR%/html. 48 | goto end 49 | ) 50 | 51 | if "%1" == "dirhtml" ( 52 | %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml 53 | if errorlevel 1 exit /b 1 54 | echo. 55 | echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. 56 | goto end 57 | ) 58 | 59 | if "%1" == "singlehtml" ( 60 | %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml 61 | if errorlevel 1 exit /b 1 62 | echo. 63 | echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. 64 | goto end 65 | ) 66 | 67 | if "%1" == "pickle" ( 68 | %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle 69 | if errorlevel 1 exit /b 1 70 | echo. 71 | echo.Build finished; now you can process the pickle files. 72 | goto end 73 | ) 74 | 75 | if "%1" == "json" ( 76 | %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json 77 | if errorlevel 1 exit /b 1 78 | echo. 79 | echo.Build finished; now you can process the JSON files. 80 | goto end 81 | ) 82 | 83 | if "%1" == "htmlhelp" ( 84 | %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp 85 | if errorlevel 1 exit /b 1 86 | echo. 87 | echo.Build finished; now you can run HTML Help Workshop with the ^ 88 | .hhp project file in %BUILDDIR%/htmlhelp. 89 | goto end 90 | ) 91 | 92 | if "%1" == "qthelp" ( 93 | %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp 94 | if errorlevel 1 exit /b 1 95 | echo. 96 | echo.Build finished; now you can run "qcollectiongenerator" with the ^ 97 | .qhcp project file in %BUILDDIR%/qthelp, like this: 98 | echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Flask-MongoKit.qhcp 99 | echo.To view the help file: 100 | echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Flask-MongoKit.ghc 101 | goto end 102 | ) 103 | 104 | if "%1" == "devhelp" ( 105 | %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp 106 | if errorlevel 1 exit /b 1 107 | echo. 108 | echo.Build finished. 109 | goto end 110 | ) 111 | 112 | if "%1" == "epub" ( 113 | %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub 114 | if errorlevel 1 exit /b 1 115 | echo. 116 | echo.Build finished. The epub file is in %BUILDDIR%/epub. 117 | goto end 118 | ) 119 | 120 | if "%1" == "latex" ( 121 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 122 | if errorlevel 1 exit /b 1 123 | echo. 124 | echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. 125 | goto end 126 | ) 127 | 128 | if "%1" == "text" ( 129 | %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text 130 | if errorlevel 1 exit /b 1 131 | echo. 132 | echo.Build finished. The text files are in %BUILDDIR%/text. 133 | goto end 134 | ) 135 | 136 | if "%1" == "man" ( 137 | %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man 138 | if errorlevel 1 exit /b 1 139 | echo. 140 | echo.Build finished. The manual pages are in %BUILDDIR%/man. 141 | goto end 142 | ) 143 | 144 | if "%1" == "changes" ( 145 | %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes 146 | if errorlevel 1 exit /b 1 147 | echo. 148 | echo.The overview file is in %BUILDDIR%/changes. 149 | goto end 150 | ) 151 | 152 | if "%1" == "linkcheck" ( 153 | %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck 154 | if errorlevel 1 exit /b 1 155 | echo. 156 | echo.Link check complete; look for any errors in the above output ^ 157 | or in %BUILDDIR%/linkcheck/output.txt. 158 | goto end 159 | ) 160 | 161 | if "%1" == "doctest" ( 162 | %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest 163 | if errorlevel 1 exit /b 1 164 | echo. 165 | echo.Testing of doctests in the sources finished, look at the ^ 166 | results in %BUILDDIR%/doctest/output.txt. 167 | goto end 168 | ) 169 | 170 | :end 171 | -------------------------------------------------------------------------------- /docs/_themes/flask_small/static/flasky.css_t: -------------------------------------------------------------------------------- 1 | /* 2 | * flasky.css_t 3 | * ~~~~~~~~~~~~ 4 | * 5 | * Sphinx stylesheet -- flasky theme based on nature theme. 6 | * 7 | * :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS. 8 | * :license: BSD, see LICENSE for details. 9 | * 10 | */ 11 | 12 | @import url("basic.css"); 13 | 14 | /* -- page layout ----------------------------------------------------------- */ 15 | 16 | body { 17 | font-family: 'Georgia', serif; 18 | font-size: 17px; 19 | color: #000; 20 | background: white; 21 | margin: 0; 22 | padding: 0; 23 | } 24 | 25 | div.documentwrapper { 26 | float: left; 27 | width: 100%; 28 | } 29 | 30 | div.bodywrapper { 31 | margin: 40px auto 0 auto; 32 | width: 700px; 33 | } 34 | 35 | hr { 36 | border: 1px solid #B1B4B6; 37 | } 38 | 39 | div.body { 40 | background-color: #ffffff; 41 | color: #3E4349; 42 | padding: 0 30px 30px 30px; 43 | } 44 | 45 | img.floatingflask { 46 | padding: 0 0 10px 10px; 47 | float: right; 48 | } 49 | 50 | div.footer { 51 | text-align: right; 52 | color: #888; 53 | padding: 10px; 54 | font-size: 14px; 55 | width: 650px; 56 | margin: 0 auto 40px auto; 57 | } 58 | 59 | div.footer a { 60 | color: #888; 61 | text-decoration: underline; 62 | } 63 | 64 | div.related { 65 | line-height: 32px; 66 | color: #888; 67 | } 68 | 69 | div.related ul { 70 | padding: 0 0 0 10px; 71 | } 72 | 73 | div.related a { 74 | color: #444; 75 | } 76 | 77 | /* -- body styles ----------------------------------------------------------- */ 78 | 79 | a { 80 | color: #004B6B; 81 | text-decoration: underline; 82 | } 83 | 84 | a:hover { 85 | color: #6D4100; 86 | text-decoration: underline; 87 | } 88 | 89 | div.body { 90 | padding-bottom: 40px; /* saved for footer */ 91 | } 92 | 93 | div.body h1, 94 | div.body h2, 95 | div.body h3, 96 | div.body h4, 97 | div.body h5, 98 | div.body h6 { 99 | font-family: 'Garamond', 'Georgia', serif; 100 | font-weight: normal; 101 | margin: 30px 0px 10px 0px; 102 | padding: 0; 103 | } 104 | 105 | {% if theme_index_logo %} 106 | div.indexwrapper h1 { 107 | text-indent: -999999px; 108 | background: url({{ theme_index_logo }}) no-repeat center center; 109 | height: {{ theme_index_logo_height }}; 110 | } 111 | {% endif %} 112 | 113 | div.body h2 { font-size: 180%; } 114 | div.body h3 { font-size: 150%; } 115 | div.body h4 { font-size: 130%; } 116 | div.body h5 { font-size: 100%; } 117 | div.body h6 { font-size: 100%; } 118 | 119 | a.headerlink { 120 | color: white; 121 | padding: 0 4px; 122 | text-decoration: none; 123 | } 124 | 125 | a.headerlink:hover { 126 | color: #444; 127 | background: #eaeaea; 128 | } 129 | 130 | div.body p, div.body dd, div.body li { 131 | line-height: 1.4em; 132 | } 133 | 134 | div.admonition { 135 | background: #fafafa; 136 | margin: 20px -30px; 137 | padding: 10px 30px; 138 | border-top: 1px solid #ccc; 139 | border-bottom: 1px solid #ccc; 140 | } 141 | 142 | div.admonition p.admonition-title { 143 | font-family: 'Garamond', 'Georgia', serif; 144 | font-weight: normal; 145 | font-size: 24px; 146 | margin: 0 0 10px 0; 147 | padding: 0; 148 | line-height: 1; 149 | } 150 | 151 | div.admonition p.last { 152 | margin-bottom: 0; 153 | } 154 | 155 | div.highlight{ 156 | background-color: white; 157 | } 158 | 159 | dt:target, .highlight { 160 | background: #FAF3E8; 161 | } 162 | 163 | div.note { 164 | background-color: #eee; 165 | border: 1px solid #ccc; 166 | } 167 | 168 | div.seealso { 169 | background-color: #ffc; 170 | border: 1px solid #ff6; 171 | } 172 | 173 | div.topic { 174 | background-color: #eee; 175 | } 176 | 177 | div.warning { 178 | background-color: #ffe4e4; 179 | border: 1px solid #f66; 180 | } 181 | 182 | p.admonition-title { 183 | display: inline; 184 | } 185 | 186 | p.admonition-title:after { 187 | content: ":"; 188 | } 189 | 190 | pre, tt { 191 | font-family: 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace; 192 | font-size: 0.85em; 193 | } 194 | 195 | img.screenshot { 196 | } 197 | 198 | tt.descname, tt.descclassname { 199 | font-size: 0.95em; 200 | } 201 | 202 | tt.descname { 203 | padding-right: 0.08em; 204 | } 205 | 206 | img.screenshot { 207 | -moz-box-shadow: 2px 2px 4px #eee; 208 | -webkit-box-shadow: 2px 2px 4px #eee; 209 | box-shadow: 2px 2px 4px #eee; 210 | } 211 | 212 | table.docutils { 213 | border: 1px solid #888; 214 | -moz-box-shadow: 2px 2px 4px #eee; 215 | -webkit-box-shadow: 2px 2px 4px #eee; 216 | box-shadow: 2px 2px 4px #eee; 217 | } 218 | 219 | table.docutils td, table.docutils th { 220 | border: 1px solid #888; 221 | padding: 0.25em 0.7em; 222 | } 223 | 224 | table.field-list, table.footnote { 225 | border: none; 226 | -moz-box-shadow: none; 227 | -webkit-box-shadow: none; 228 | box-shadow: none; 229 | } 230 | 231 | table.footnote { 232 | margin: 15px 0; 233 | width: 100%; 234 | border: 1px solid #eee; 235 | } 236 | 237 | table.field-list th { 238 | padding: 0 0.8em 0 0; 239 | } 240 | 241 | table.field-list td { 242 | padding: 0; 243 | } 244 | 245 | table.footnote td { 246 | padding: 0.5em; 247 | } 248 | 249 | dl { 250 | margin: 0; 251 | padding: 0; 252 | } 253 | 254 | dl dd { 255 | margin-left: 30px; 256 | } 257 | 258 | pre { 259 | padding: 0; 260 | margin: 15px -30px; 261 | padding: 8px; 262 | line-height: 1.3em; 263 | padding: 7px 30px; 264 | background: #eee; 265 | border-radius: 2px; 266 | -moz-border-radius: 2px; 267 | -webkit-border-radius: 2px; 268 | } 269 | 270 | dl pre { 271 | margin-left: -60px; 272 | padding-left: 60px; 273 | } 274 | 275 | tt { 276 | background-color: #ecf0f3; 277 | color: #222; 278 | /* padding: 1px 2px; */ 279 | } 280 | 281 | tt.xref, a tt { 282 | background-color: #FBFBFB; 283 | } 284 | 285 | a:hover tt { 286 | background: #EEE; 287 | } 288 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | ============== 2 | Flask-MongoKit 3 | ============== 4 | .. currentmodule:: flask_mongokit 5 | 6 | Flask-MongoKit simplifies to use `MongoKit`_, a powerful `MongoDB`_ ORM 7 | in Flask applications. If you find bugs or want to support this extension you can find the source code `here`_. 8 | 9 | .. _MongoKit: http://namlook.github.com/mongokit/ 10 | .. _MongoDB: http://www.mongodb.org/ 11 | .. _here: https://github.com/jarus/flask-mongokit/ 12 | 13 | Installation 14 | ============ 15 | The installation is thanks to the Python Package Index and `pip`_ really simple. 16 | 17 | .. code-block:: console 18 | 19 | $ pip install Flask-MongoKit 20 | 21 | If you only can use `easy_install` than use 22 | 23 | .. code-block:: console 24 | 25 | $ easy_install Flask-MongoKit 26 | 27 | .. _pip: http://pip.openplans.org/ 28 | 29 | Flask-MongoKit requires to run some packages (they will be installed automatically if they not already installed): 30 | 31 | * Flask 32 | * MongoKit 33 | * pymongo 34 | 35 | Your first Document 36 | =================== 37 | It is very simple to use MongoKit in your Flask application. Let's create a simple ToDo application. 38 | 39 | .. code-block:: python 40 | 41 | from datetime import datetime 42 | 43 | from flask import Flask, request, render_template, redirect, url_for 44 | from flask.ext.mongokit import MongoKit, Document 45 | 46 | app = Flask(__name__) 47 | 48 | class Task(Document): 49 | __collection__ = 'tasks' 50 | structure = { 51 | 'title': unicode, 52 | 'text': unicode, 53 | 'creation': datetime, 54 | } 55 | required_fields = ['title', 'creation'] 56 | default_values = {'creation': datetime.utcnow} 57 | use_dot_notation = True 58 | 59 | db = MongoKit(app) 60 | db.register([Task]) 61 | 62 | As you can see we create a document model as class *Task* which uses Document from flask.ext.mongokit as parent class. In this model we describe the structure of our document and we can set a list of required fields and default values. The :class:`flask.ext.mongokit.Document` is beside some extensions the same like :class:`mongokit.Document` so if you want to know more about the core features of the Document class please look into the `MongoKit documentation`_. For using the the document model we must register it with the connection. But we use the :meth:`~flask.ext.mongokit.MongoKit.register` method from the :class:`flask.ext.mongokit.MongoKit` class. 63 | 64 | Now we need a view to add a new task like this. 65 | 66 | .. code-block:: python 67 | 68 | @app.route('/new', methods=["GET", "POST"]) 69 | def new_task(): 70 | if request.method == 'POST': 71 | task = db.Task() 72 | task.title = request.form['title'] 73 | task.text = request.form['text'] 74 | task.save() 75 | return redirect(url_for('show_all')) 76 | return render_template('new.html') 77 | 78 | If someone now clicks on the submit button of the form your application will create a new instance of your Task model class. After that we set title and text of the task and save it into your MongoDB. 79 | 80 | But now we want to get a list of task, so we add an other view. 81 | 82 | .. code-block:: python 83 | 84 | @app.route('/') 85 | def show_all(): 86 | tasks = db.Task.find() 87 | return render_template('list.html', tasks=tasks) 88 | 89 | This view is very simple. You can see we only call the :meth:`find` method and put the result into our template. Now we have a running example that works simple with a MongoDB inside a Flask application. 90 | 91 | If you want to see a full example of Flask-MongoKit look inside the repository. You will find there this ToDo application with the matching templates. 92 | 93 | .. _MongoKit documentation: http://namlook.github.com/mongokit/descriptors.html 94 | 95 | Configuration values 96 | -------------------- 97 | 98 | The following configuration variables are used in Flask-MongoKit: 99 | 100 | .. tabularcolumns:: |p{6.5cm}|p{8.5cm}| 101 | 102 | =============================== ========================================= 103 | ``MONGODB_DATABASE`` The database name that should used. 104 | 105 | *Default value:* ``flask`` 106 | ``MONGODB_HOST`` Hostname or IP address of the MongoDB host. 107 | 108 | *Default value:* ``localhost`` 109 | ``MONGODB_PORT`` Listening port of the MongoDB host. 110 | 111 | *Default value:* ``27017`` 112 | ``MONGODB_USERNAME`` If you need authentication than you can set 113 | there your username. 114 | 115 | *Default value:* ``None`` 116 | ``MONGODB_PASSWORD`` Password for authentication. 117 | 118 | *Default value:* ``None`` 119 | ``MONGODB_TZ_AWARE`` It sets the tz_aware parameter to True when 120 | creating a connection. The timezone of datetime 121 | objects returned from MongoDB will always be UTC. 122 | 123 | *Default value:* ``False`` 124 | =============================== ========================================= 125 | 126 | .. _request-app-context: 127 | 128 | Request and App context 129 | ----------------------- 130 | 131 | If you want to make some operations on your MongoDB with Flask-MongoKit you need a context like the request or app context. If you want to use it for example in Flask-Script than the best choise is the app context (implemented since Flask v0.9). There is a small example how to use the app context.:: 132 | 133 | from flask import Flask 134 | from flask.ext.mongokit import MongoKit 135 | 136 | app = Flask(__name__) 137 | db = MongoKit(app) 138 | 139 | with app.app_context(): 140 | db['my_collection'].insert({'x': 5}) 141 | print db['my_collection'].find_one({'x': 5}) 142 | 143 | You can also use it in the normal request context like insite of a view function or in the test request context like the following example.:: 144 | 145 | with app.test_request_context('/'): 146 | db['my_collection'].insert({'x': 5}) 147 | print db['my_collection'].find_one({'x': 5}) 148 | 149 | Changelog 150 | ========= 151 | 152 | * **0.6 (08.07.2012)** 153 | 154 | * Use the new app context and again the old request context, 155 | see :ref:`request-app-context`. 156 | * The MongoKit object is now subscriptable and support the typical syntax to 157 | get a collection.:: 158 | 159 | db['my_collection'].insert({'x': 5}) 160 | 161 | * Restructured and improved test suite. 162 | * Sounds crazy but improved python2.5 support. 163 | 164 | * **0.5 (02.07.2012)** 165 | 166 | * You don't need a request context anymore for the mongodb connection. 167 | (A bad decision ... look in 0.6) 168 | 169 | * **0.4 (23.02.2012)** 170 | 171 | * Support new import system of flask. Use now:: 172 | 173 | form flask.ext.mongokit import Mongokit 174 | 175 | 176 | API Documentation 177 | ================= 178 | 179 | .. autoclass:: MongoKit 180 | :members: 181 | 182 | .. autoclass:: Document 183 | :members: 184 | 185 | .. autoclass:: BSONObjectIdConverter 186 | :members: 187 | -------------------------------------------------------------------------------- /docs/_themes/flask/static/flasky.css_t: -------------------------------------------------------------------------------- 1 | /* 2 | * flasky.css_t 3 | * ~~~~~~~~~~~~ 4 | * 5 | * :copyright: Copyright 2010 by Armin Ronacher. 6 | * :license: Flask Design License, see LICENSE for details. 7 | */ 8 | 9 | {% set page_width = '940px' %} 10 | {% set sidebar_width = '220px' %} 11 | 12 | @import url("basic.css"); 13 | 14 | /* -- page layout ----------------------------------------------------------- */ 15 | 16 | body { 17 | font-family: 'Georgia', serif; 18 | font-size: 17px; 19 | background-color: white; 20 | color: #000; 21 | margin: 0; 22 | padding: 0; 23 | } 24 | 25 | div.document { 26 | width: {{ page_width }}; 27 | margin: 30px auto 0 auto; 28 | } 29 | 30 | div.documentwrapper { 31 | float: left; 32 | width: 100%; 33 | } 34 | 35 | div.bodywrapper { 36 | margin: 0 0 0 {{ sidebar_width }}; 37 | } 38 | 39 | div.sphinxsidebar { 40 | width: {{ sidebar_width }}; 41 | } 42 | 43 | hr { 44 | border: 1px solid #B1B4B6; 45 | } 46 | 47 | div.body { 48 | background-color: #ffffff; 49 | color: #3E4349; 50 | padding: 0 30px 0 30px; 51 | } 52 | 53 | img.floatingflask { 54 | padding: 0 0 10px 10px; 55 | float: right; 56 | } 57 | 58 | div.footer { 59 | width: {{ page_width }}; 60 | margin: 20px auto 30px auto; 61 | font-size: 14px; 62 | color: #888; 63 | text-align: right; 64 | } 65 | 66 | div.footer a { 67 | color: #888; 68 | } 69 | 70 | div.related { 71 | display: none; 72 | } 73 | 74 | div.sphinxsidebar a { 75 | color: #444; 76 | text-decoration: none; 77 | border-bottom: 1px dotted #999; 78 | } 79 | 80 | div.sphinxsidebar a:hover { 81 | border-bottom: 1px solid #999; 82 | } 83 | 84 | div.sphinxsidebar { 85 | font-size: 14px; 86 | line-height: 1.5; 87 | } 88 | 89 | div.sphinxsidebarwrapper { 90 | padding: 18px 10px; 91 | } 92 | 93 | div.sphinxsidebarwrapper p.logo { 94 | padding: 0 0 20px 0; 95 | margin: 0; 96 | text-align: center; 97 | } 98 | 99 | div.sphinxsidebar h3, 100 | div.sphinxsidebar h4 { 101 | font-family: 'Garamond', 'Georgia', serif; 102 | color: #444; 103 | font-size: 24px; 104 | font-weight: normal; 105 | margin: 0 0 5px 0; 106 | padding: 0; 107 | } 108 | 109 | div.sphinxsidebar h4 { 110 | font-size: 20px; 111 | } 112 | 113 | div.sphinxsidebar h3 a { 114 | color: #444; 115 | } 116 | 117 | div.sphinxsidebar p.logo a, 118 | div.sphinxsidebar h3 a, 119 | div.sphinxsidebar p.logo a:hover, 120 | div.sphinxsidebar h3 a:hover { 121 | border: none; 122 | } 123 | 124 | div.sphinxsidebar p { 125 | color: #555; 126 | margin: 10px 0; 127 | } 128 | 129 | div.sphinxsidebar ul { 130 | margin: 10px 0; 131 | padding: 0; 132 | color: #000; 133 | } 134 | 135 | div.sphinxsidebar input { 136 | border: 1px solid #ccc; 137 | font-family: 'Georgia', serif; 138 | font-size: 1em; 139 | } 140 | 141 | /* -- body styles ----------------------------------------------------------- */ 142 | 143 | a { 144 | color: #004B6B; 145 | text-decoration: underline; 146 | } 147 | 148 | a:hover { 149 | color: #6D4100; 150 | text-decoration: underline; 151 | } 152 | 153 | div.body h1, 154 | div.body h2, 155 | div.body h3, 156 | div.body h4, 157 | div.body h5, 158 | div.body h6 { 159 | font-family: 'Garamond', 'Georgia', serif; 160 | font-weight: normal; 161 | margin: 30px 0px 10px 0px; 162 | padding: 0; 163 | } 164 | 165 | {% if theme_index_logo %} 166 | div.indexwrapper h1 { 167 | text-indent: -999999px; 168 | background: url({{ theme_index_logo }}) no-repeat center center; 169 | height: {{ theme_index_logo_height }}; 170 | } 171 | {% endif %} 172 | 173 | div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; } 174 | div.body h2 { font-size: 180%; } 175 | div.body h3 { font-size: 150%; } 176 | div.body h4 { font-size: 130%; } 177 | div.body h5 { font-size: 100%; } 178 | div.body h6 { font-size: 100%; } 179 | 180 | a.headerlink { 181 | color: #ddd; 182 | padding: 0 4px; 183 | text-decoration: none; 184 | } 185 | 186 | a.headerlink:hover { 187 | color: #444; 188 | background: #eaeaea; 189 | } 190 | 191 | div.body p, div.body dd, div.body li { 192 | line-height: 1.4em; 193 | } 194 | 195 | div.admonition { 196 | background: #fafafa; 197 | margin: 20px -30px; 198 | padding: 10px 30px; 199 | border-top: 1px solid #ccc; 200 | border-bottom: 1px solid #ccc; 201 | } 202 | 203 | div.admonition tt.xref, div.admonition a tt { 204 | border-bottom: 1px solid #fafafa; 205 | } 206 | 207 | dd div.admonition { 208 | margin-left: -60px; 209 | padding-left: 60px; 210 | } 211 | 212 | div.admonition p.admonition-title { 213 | font-family: 'Garamond', 'Georgia', serif; 214 | font-weight: normal; 215 | font-size: 24px; 216 | margin: 0 0 10px 0; 217 | padding: 0; 218 | line-height: 1; 219 | } 220 | 221 | div.admonition p.last { 222 | margin-bottom: 0; 223 | } 224 | 225 | div.highlight { 226 | background-color: white; 227 | } 228 | 229 | dt:target, .highlight { 230 | background: #FAF3E8; 231 | } 232 | 233 | div.note { 234 | background-color: #eee; 235 | border: 1px solid #ccc; 236 | } 237 | 238 | div.seealso { 239 | background-color: #ffc; 240 | border: 1px solid #ff6; 241 | } 242 | 243 | div.topic { 244 | background-color: #eee; 245 | } 246 | 247 | p.admonition-title { 248 | display: inline; 249 | } 250 | 251 | p.admonition-title:after { 252 | content: ":"; 253 | } 254 | 255 | pre, tt { 256 | font-family: 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace; 257 | font-size: 0.9em; 258 | } 259 | 260 | img.screenshot { 261 | } 262 | 263 | tt.descname, tt.descclassname { 264 | font-size: 0.95em; 265 | } 266 | 267 | tt.descname { 268 | padding-right: 0.08em; 269 | } 270 | 271 | img.screenshot { 272 | -moz-box-shadow: 2px 2px 4px #eee; 273 | -webkit-box-shadow: 2px 2px 4px #eee; 274 | box-shadow: 2px 2px 4px #eee; 275 | } 276 | 277 | table.docutils { 278 | border: 1px solid #888; 279 | -moz-box-shadow: 2px 2px 4px #eee; 280 | -webkit-box-shadow: 2px 2px 4px #eee; 281 | box-shadow: 2px 2px 4px #eee; 282 | } 283 | 284 | table.docutils td, table.docutils th { 285 | border: 1px solid #888; 286 | padding: 0.25em 0.7em; 287 | } 288 | 289 | table.field-list, table.footnote { 290 | border: none; 291 | -moz-box-shadow: none; 292 | -webkit-box-shadow: none; 293 | box-shadow: none; 294 | } 295 | 296 | table.footnote { 297 | margin: 15px 0; 298 | width: 100%; 299 | border: 1px solid #eee; 300 | background: #fdfdfd; 301 | font-size: 0.9em; 302 | } 303 | 304 | table.footnote + table.footnote { 305 | margin-top: -15px; 306 | border-top: none; 307 | } 308 | 309 | table.field-list th { 310 | padding: 0 0.8em 0 0; 311 | } 312 | 313 | table.field-list td { 314 | padding: 0; 315 | } 316 | 317 | table.footnote td.label { 318 | width: 0px; 319 | padding: 0.3em 0 0.3em 0.5em; 320 | } 321 | 322 | table.footnote td { 323 | padding: 0.3em 0.5em; 324 | } 325 | 326 | dl { 327 | margin: 0; 328 | padding: 0; 329 | } 330 | 331 | dl dd { 332 | margin-left: 30px; 333 | } 334 | 335 | blockquote { 336 | margin: 0 0 0 30px; 337 | padding: 0; 338 | } 339 | 340 | ul, ol { 341 | margin: 10px 0 10px 30px; 342 | padding: 0; 343 | } 344 | 345 | pre { 346 | background: #eee; 347 | padding: 7px 30px; 348 | margin: 15px -30px; 349 | line-height: 1.3em; 350 | } 351 | 352 | dl pre, blockquote pre, li pre { 353 | margin-left: -60px; 354 | padding-left: 60px; 355 | } 356 | 357 | dl dl pre { 358 | margin-left: -90px; 359 | padding-left: 90px; 360 | } 361 | 362 | tt { 363 | background-color: #ecf0f3; 364 | color: #222; 365 | /* padding: 1px 2px; */ 366 | } 367 | 368 | tt.xref, a tt { 369 | background-color: #FBFBFB; 370 | border-bottom: 1px solid white; 371 | } 372 | 373 | a.reference { 374 | text-decoration: none; 375 | border-bottom: 1px dotted #004B6B; 376 | } 377 | 378 | a.reference:hover { 379 | border-bottom: 1px solid #6D4100; 380 | } 381 | 382 | a.footnote-reference { 383 | text-decoration: none; 384 | font-size: 0.7em; 385 | vertical-align: top; 386 | border-bottom: 1px dotted #004B6B; 387 | } 388 | 389 | a.footnote-reference:hover { 390 | border-bottom: 1px solid #6D4100; 391 | } 392 | 393 | a:hover tt { 394 | background: #EEE; 395 | } 396 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Flask-MongoKit documentation build configuration file, created by 4 | # sphinx-quickstart on Tue Aug 16 21:56:43 2011. 5 | # 6 | # This file is execfile()d with the current directory set to its containing dir. 7 | # 8 | # Note that not all possible configuration values are present in this 9 | # autogenerated file. 10 | # 11 | # All configuration values have a default; values that are commented out 12 | # serve to show the default. 13 | 14 | import sys, os 15 | 16 | # If extensions (or modules to document with autodoc) are in another directory, 17 | # add these directories to sys.path here. If the directory is relative to the 18 | # documentation root, use os.path.abspath to make it absolute, like shown here. 19 | sys.path.append(os.path.abspath('_themes')) 20 | 21 | # -- General configuration ----------------------------------------------------- 22 | 23 | # If your documentation needs a minimal Sphinx version, state it here. 24 | #needs_sphinx = '1.0' 25 | 26 | # Add any Sphinx extension module names here, as strings. They can be extensions 27 | # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. 28 | extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 'sphinx.ext.todo'] 29 | 30 | # Add any paths that contain templates here, relative to this directory. 31 | templates_path = ['_templates'] 32 | 33 | # The suffix of source filenames. 34 | source_suffix = '.rst' 35 | 36 | # The encoding of source files. 37 | #source_encoding = 'utf-8-sig' 38 | 39 | # The master toctree document. 40 | master_doc = 'index' 41 | 42 | # General information about the project. 43 | project = u'Flask-MongoKit' 44 | copyright = u'2011, Christoph Heer' 45 | 46 | # The version info for the project you're documenting, acts as replacement for 47 | # |version| and |release|, also used in various other places throughout the 48 | # built documents. 49 | # 50 | # The short X.Y version. 51 | version = '0.2' 52 | # The full version, including alpha/beta/rc tags. 53 | release = '0.2' 54 | 55 | # The language for content autogenerated by Sphinx. Refer to documentation 56 | # for a list of supported languages. 57 | #language = None 58 | 59 | # There are two options for replacing |today|: either, you set today to some 60 | # non-false value, then it is used: 61 | #today = '' 62 | # Else, today_fmt is used as the format for a strftime call. 63 | #today_fmt = '%B %d, %Y' 64 | 65 | # List of patterns, relative to source directory, that match files and 66 | # directories to ignore when looking for source files. 67 | exclude_patterns = ['_build'] 68 | 69 | # The reST default role (used for this markup: `text`) to use for all documents. 70 | #default_role = None 71 | 72 | # If true, '()' will be appended to :func: etc. cross-reference text. 73 | #add_function_parentheses = True 74 | 75 | # If true, the current module name will be prepended to all description 76 | # unit titles (such as .. function::). 77 | #add_module_names = True 78 | 79 | # If true, sectionauthor and moduleauthor directives will be shown in the 80 | # output. They are ignored by default. 81 | #show_authors = False 82 | 83 | # The name of the Pygments (syntax highlighting) style to use. 84 | #pygments_style = 'sphinx' 85 | 86 | # A list of ignored prefixes for module index sorting. 87 | #modindex_common_prefix = [] 88 | 89 | 90 | # -- Options for HTML output --------------------------------------------------- 91 | 92 | # The theme to use for HTML and HTML Help pages. See the documentation for 93 | # a list of builtin themes. 94 | html_theme = 'flask_small' 95 | 96 | # Theme options are theme-specific and customize the look and feel of a theme 97 | # further. For a list of options available for each theme, see the 98 | # documentation. 99 | html_theme_options = { 100 | 'github_fork': 'jarus/flask-mongokit', 101 | 'index_logo': 'flask-mongokit.png' 102 | } 103 | 104 | # Add any paths that contain custom themes here, relative to this directory. 105 | html_theme_path = ['_themes'] 106 | 107 | # The name for this set of Sphinx documents. If None, it defaults to 108 | # " v documentation". 109 | #html_title = None 110 | 111 | # A shorter title for the navigation bar. Default is the same as html_title. 112 | #html_short_title = None 113 | 114 | # The name of an image file (relative to this directory) to place at the top 115 | # of the sidebar. 116 | #html_logo = None 117 | 118 | # The name of an image file (within the static path) to use as favicon of the 119 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 120 | # pixels large. 121 | #html_favicon = None 122 | 123 | # Add any paths that contain custom static files (such as style sheets) here, 124 | # relative to this directory. They are copied after the builtin static files, 125 | # so a file named "default.css" will overwrite the builtin "default.css". 126 | html_static_path = ['_static'] 127 | 128 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 129 | # using the given strftime format. 130 | #html_last_updated_fmt = '%b %d, %Y' 131 | 132 | # If true, SmartyPants will be used to convert quotes and dashes to 133 | # typographically correct entities. 134 | #html_use_smartypants = True 135 | 136 | # Custom sidebar templates, maps document names to template names. 137 | #html_sidebars = {} 138 | 139 | # Additional templates that should be rendered to pages, maps page names to 140 | # template names. 141 | #html_additional_pages = {} 142 | 143 | # If false, no module index is generated. 144 | #html_domain_indices = True 145 | 146 | # If false, no index is generated. 147 | #html_use_index = True 148 | 149 | # If true, the index is split into individual pages for each letter. 150 | #html_split_index = False 151 | 152 | # If true, links to the reST sources are added to the pages. 153 | #html_show_sourcelink = True 154 | 155 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 156 | #html_show_sphinx = True 157 | 158 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 159 | #html_show_copyright = True 160 | 161 | # If true, an OpenSearch description file will be output, and all pages will 162 | # contain a tag referring to it. The value of this option must be the 163 | # base URL from which the finished HTML is served. 164 | #html_use_opensearch = '' 165 | 166 | # This is the file name suffix for HTML files (e.g. ".xhtml"). 167 | #html_file_suffix = None 168 | 169 | # Output file base name for HTML help builder. 170 | htmlhelp_basename = 'Flask-MongoKitdoc' 171 | 172 | 173 | # -- Options for LaTeX output -------------------------------------------------- 174 | 175 | # The paper size ('letter' or 'a4'). 176 | #latex_paper_size = 'letter' 177 | 178 | # The font size ('10pt', '11pt' or '12pt'). 179 | #latex_font_size = '10pt' 180 | 181 | # Grouping the document tree into LaTeX files. List of tuples 182 | # (source start file, target name, title, author, documentclass [howto/manual]). 183 | latex_documents = [ 184 | ('index', 'Flask-MongoKit.tex', u'Flask-MongoKit Documentation', 185 | u'Christoph Heer', 'manual'), 186 | ] 187 | 188 | # The name of an image file (relative to this directory) to place at the top of 189 | # the title page. 190 | #latex_logo = None 191 | 192 | # For "manual" documents, if this is true, then toplevel headings are parts, 193 | # not chapters. 194 | #latex_use_parts = False 195 | 196 | # If true, show page references after internal links. 197 | #latex_show_pagerefs = False 198 | 199 | # If true, show URL addresses after external links. 200 | #latex_show_urls = False 201 | 202 | # Additional stuff for the LaTeX preamble. 203 | #latex_preamble = '' 204 | 205 | # Documents to append as an appendix to all manuals. 206 | #latex_appendices = [] 207 | 208 | # If false, no module index is generated. 209 | #latex_domain_indices = True 210 | 211 | 212 | # -- Options for manual page output -------------------------------------------- 213 | 214 | # One entry per manual page. List of tuples 215 | # (source start file, name, description, authors, manual section). 216 | man_pages = [ 217 | ('index', 'flask-mongokit', u'Flask-MongoKit Documentation', 218 | [u'Christoph Heer'], 1) 219 | ] 220 | 221 | # Example configuration for intersphinx: refer to the Python standard library. 222 | intersphinx_mapping = { 223 | 'python': ('http://docs.python.org/', None), 224 | 'flask': ('http://flask.pocoo.org/docs/', None), 225 | 'mongokit': ('http://namlook.github.com/mongokit/', None), 226 | 'pymongo': ('http://api.mongodb.org/python/current/', None), 227 | 'bson': ('http://api.mongodb.org/python/current/', None), 228 | } -------------------------------------------------------------------------------- /flask_mongokit.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | flask.ext.mongokit 4 | ~~~~~~~~~~~~~~~~~~ 5 | 6 | Flask-MongoKit simplifies to use MongoKit, a powerful MongoDB ORM in Flask 7 | applications. 8 | 9 | :copyright: 2011 by Christoph Heer ') 37 | def show_task(task_id): 38 | task = db.Task.get_from_id(task_id) 39 | return render_template('task.html', task=task) 40 | 41 | It checks the validate of the id and converts it into a 42 | :class:`bson.objectid.ObjectId` object. The converter will be 43 | automatically registered by the initialization of 44 | :class:`~flask.ext.mongokit.MongoKit` with keyword :attr:`ObjectId`. 45 | """ 46 | 47 | def to_python(self, value): 48 | try: 49 | return bson.ObjectId(value) 50 | except bson.errors.InvalidId: 51 | raise abort(400) 52 | 53 | def to_url(self, value): 54 | return str(value) 55 | 56 | 57 | class Document(Document): 58 | def get_or_404(self, id): 59 | """This method get one document over the _id field. If there no 60 | document with this id then it will raised a 404 error. 61 | 62 | :param id: The id from the document. The most time there will be 63 | an :class:`bson.objectid.ObjectId`. 64 | """ 65 | doc = self.get_from_id(id) 66 | if doc is None: 67 | abort(404) 68 | else: 69 | return doc 70 | 71 | def find_one_or_404(self, *args, **kwargs): 72 | """This method get one document over normal query parameter like 73 | :meth:`~flask.ext.mongokit.Document.find_one` but if there no document 74 | then it will raise a 404 error. 75 | """ 76 | 77 | doc = self.find_one(*args, **kwargs) 78 | if doc is None: 79 | abort(404) 80 | else: 81 | return doc 82 | 83 | 84 | class MongoKit(object): 85 | """This class is used to integrate `MongoKit`_ into a Flask application. 86 | 87 | :param app: The Flask application will be bound to this MongoKit instance. 88 | If an app is not provided at initialization time than it 89 | must be provided later by calling :meth:`init_app` manually. 90 | 91 | .. _MongoKit: http://namlook.github.com/mongokit/ 92 | """ 93 | 94 | def __init__(self, app=None): 95 | #: :class:`list` of :class:`mongokit.Document` 96 | #: which will be automated registed at connection 97 | self.registered_documents = [] 98 | 99 | if app is not None: 100 | self.app = app 101 | self.init_app(self.app) 102 | else: 103 | self.app = None 104 | 105 | def init_app(self, app): 106 | """This method connect your ``app`` with this extension. Flask- 107 | MongoKit will now take care about to open and close the connection to 108 | your MongoDB. 109 | 110 | Also it registers the 111 | :class:`flask.ext.mongokit.BSONObjectIdConverter` 112 | as a converter with the key word **ObjectId**. 113 | 114 | :param app: The Flask application will be bound to this MongoKit 115 | instance. 116 | """ 117 | app.config.setdefault('MONGODB_HOST', '127.0.0.1') 118 | app.config.setdefault('MONGODB_PORT', 27017) 119 | app.config.setdefault('MONGODB_DATABASE', 'flask') 120 | app.config.setdefault('MONGODB_SLAVE_OKAY', False) 121 | app.config.setdefault('MONGODB_USERNAME', None) 122 | app.config.setdefault('MONGODB_PASSWORD', None) 123 | 124 | # 0.9 and later 125 | # no coverage check because there is everytime only one 126 | if hasattr(app, 'teardown_appcontext'): # pragma: no cover 127 | app.teardown_appcontext(self._teardown_request) 128 | # 0.7 to 0.8 129 | elif hasattr(app, 'teardown_request'): # pragma: no cover 130 | app.teardown_request(self._teardown_request) 131 | # Older Flask versions 132 | else: # pragma: no cover 133 | app.after_request(self._teardown_request) 134 | 135 | # register extension with app only to say "I'm here" 136 | app.extensions = getattr(app, 'extensions', {}) 137 | app.extensions['mongokit'] = self 138 | 139 | app.url_map.converters['ObjectId'] = BSONObjectIdConverter 140 | 141 | self.app = app 142 | 143 | def register(self, documents): 144 | """Register one or more :class:`mongokit.Document` instances to the 145 | connection. 146 | 147 | Can be also used as a decorator on documents: 148 | 149 | .. code-block:: python 150 | 151 | db = MongoKit(app) 152 | 153 | @db.register 154 | class Task(Document): 155 | structure = { 156 | 'title': unicode, 157 | 'text': unicode, 158 | 'creation': datetime, 159 | } 160 | 161 | :param documents: A :class:`list` of :class:`mongokit.Document`. 162 | """ 163 | 164 | #enable decorator usage as in mongokit.Connection 165 | decorator = None 166 | if not isinstance(documents, (list, tuple, set, frozenset)): 167 | # we assume that the user used this as a decorator 168 | # using @register syntax or using db.register(SomeDoc) 169 | # we stock the class object in order to return it later 170 | decorator = documents 171 | documents = [documents] 172 | 173 | for document in documents: 174 | if document not in self.registered_documents: 175 | self.registered_documents.append(document) 176 | 177 | if decorator is None: 178 | return self.registered_documents 179 | else: 180 | return decorator 181 | 182 | def connect(self): 183 | """Connect to the MongoDB server and register the documents from 184 | :attr:`registered_documents`. If you set ``MONGODB_USERNAME`` and 185 | ``MONGODB_PASSWORD`` then you will be authenticated at the 186 | ``MONGODB_DATABASE``. You can also enable timezone awareness if 187 | you set to True ``MONGODB_TZ_AWARE`. 188 | """ 189 | if self.app is None: 190 | raise RuntimeError('The flask-mongokit extension was not init to ' 191 | 'the current application. Please make sure ' 192 | 'to call init_app() first.') 193 | 194 | ctx = ctx_stack.top 195 | mongokit_connection = getattr(ctx, 'mongokit_connection', None) 196 | if mongokit_connection is None: 197 | ctx.mongokit_connection = Connection( 198 | host=ctx.app.config.get('MONGODB_HOST'), 199 | port=ctx.app.config.get('MONGODB_PORT'), 200 | slave_okay=ctx.app.config.get('MONGODB_SLAVE_OKAY'), 201 | tz_aware=ctx.app.config.get('MONGODB_TZ_AWARE', False) 202 | ) 203 | 204 | ctx.mongokit_connection.register(self.registered_documents) 205 | 206 | mongokit_database = getattr(ctx, 'mongokit_database', None) 207 | if mongokit_database is None: 208 | ctx.mongokit_database = Database( 209 | ctx.mongokit_connection, 210 | ctx.app.config.get('MONGODB_DATABASE') 211 | ) 212 | 213 | if ctx.app.config.get('MONGODB_USERNAME') is not None: 214 | try: 215 | auth_success = ctx.mongokit_database.authenticate( 216 | ctx.app.config.get('MONGODB_USERNAME'), 217 | ctx.app.config.get('MONGODB_PASSWORD') 218 | ) 219 | except OperationFailure: 220 | auth_success = False 221 | 222 | if not auth_success: 223 | raise AuthenticationIncorrect('Server authentication failed') 224 | 225 | @property 226 | def connected(self): 227 | """Connection status to your MongoDB.""" 228 | ctx = ctx_stack.top 229 | return getattr(ctx, 'mongokit_connection', None) is not None 230 | 231 | def disconnect(self): 232 | """Close the connection to your MongoDB.""" 233 | if self.connected: 234 | ctx = ctx_stack.top 235 | ctx.mongokit_connection.disconnect() 236 | del ctx.mongokit_connection 237 | del ctx.mongokit_database 238 | 239 | def _teardown_request(self, response): 240 | self.disconnect() 241 | return response 242 | 243 | def __getattr__(self, name, **kwargs): 244 | if not self.connected: 245 | self.connect() 246 | 247 | mongokit_database = getattr(ctx_stack.top, "mongokit_database") 248 | return getattr(mongokit_database, name) 249 | 250 | def __getitem__(self, name): 251 | if not self.connected: 252 | self.connect() 253 | 254 | mongokit_database = getattr(ctx_stack.top, "mongokit_database") 255 | return mongokit_database[name] 256 | -------------------------------------------------------------------------------- /tests/test_base.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import unittest 4 | import os 5 | 6 | from datetime import datetime 7 | 8 | from flask import Flask 9 | from flask_mongokit import MongoKit, BSONObjectIdConverter, \ 10 | Document, Collection, AuthenticationIncorrect 11 | from werkzeug.exceptions import BadRequest, NotFound 12 | from bson import ObjectId 13 | from pymongo import Connection 14 | from pymongo.collection import Collection 15 | 16 | class BlogPost(Document): 17 | __collection__ = "posts" 18 | structure = { 19 | 'title': unicode, 20 | 'body': unicode, 21 | 'author': unicode, 22 | 'date_creation': datetime, 23 | 'rank': int, 24 | 'tags': [unicode], 25 | } 26 | required_fields = ['title', 'author', 'date_creation'] 27 | default_values = {'rank': 0, 'date_creation': datetime.utcnow} 28 | use_dot_notation = True 29 | 30 | def create_app(): 31 | app = Flask(__name__) 32 | app.config['TESTING'] = True 33 | app.config['MONGODB_DATABASE'] = 'flask_testing' 34 | 35 | maybe_conf_file = os.path.join(os.getcwd(), "config_test.cfg") 36 | if os.path.exists(maybe_conf_file): 37 | app.config.from_pyfile(maybe_conf_file) 38 | 39 | return app 40 | 41 | class TestCaseContextIndependent(unittest.TestCase): 42 | def setUp(self): 43 | self.app = create_app() 44 | self.db = MongoKit(self.app) 45 | 46 | def tearDown(self): 47 | pass 48 | 49 | def test_register_document(self): 50 | self.db.register([BlogPost]) 51 | 52 | assert len(self.db.registered_documents) > 0 53 | assert self.db.registered_documents[0] == BlogPost 54 | 55 | def test_bson_object_id_converter(self): 56 | converter = BSONObjectIdConverter("/") 57 | 58 | self.assertRaises(BadRequest, converter.to_python, ("132")) 59 | assert converter.to_python("4e4ac5cfffc84958fa1f45fb") == \ 60 | ObjectId("4e4ac5cfffc84958fa1f45fb") 61 | assert converter.to_url(ObjectId("4e4ac5cfffc84958fa1f45fb")) == \ 62 | "4e4ac5cfffc84958fa1f45fb" 63 | 64 | def test_is_extension_registerd(self): 65 | assert hasattr(self.app, 'extensions') 66 | assert 'mongokit' in self.app.extensions 67 | assert self.app.extensions['mongokit'] == self.db 68 | 69 | class BaseTestCaseInitAppWithContext(): 70 | def setUp(self): 71 | self.app = create_app() 72 | 73 | def test_init_later(self): 74 | self.db = MongoKit() 75 | self.assertRaises(RuntimeError, self.db.connect) 76 | 77 | self.db.init_app(self.app) 78 | self.db.connect() 79 | assert self.db.connected 80 | 81 | def test_init_immediately(self): 82 | self.db = MongoKit(self.app) 83 | self.db.connect() 84 | assert self.db.connected 85 | 86 | class BaseTestCaseWithContext(): 87 | 88 | def test_initialization(self): 89 | assert isinstance(self.db, MongoKit) 90 | assert self.db.name == self.app.config['MONGODB_DATABASE'] 91 | assert isinstance(self.db.test, Collection) 92 | 93 | def test_property_connected(self): 94 | assert not self.db.connected 95 | 96 | self.db.connect() 97 | assert self.db.connected 98 | 99 | self.db.disconnect() 100 | assert not self.db.connected 101 | 102 | self.db.collection_names() 103 | assert self.db.connected 104 | 105 | def test_subscriptable(self): 106 | assert isinstance(self.db['test'], Collection) 107 | assert self.db['test'] == self.db.test 108 | 109 | def test_save_and_find_document(self): 110 | self.db.register([BlogPost]) 111 | 112 | assert len(self.db.registered_documents) > 0 113 | assert self.db.registered_documents[0] == BlogPost 114 | 115 | post = self.db.BlogPost() 116 | post.title = u"Flask-MongoKit" 117 | post.body = u"Flask-MongoKit is a layer between Flask and MongoKit" 118 | post.author = u"Christoph Heer" 119 | post.save() 120 | 121 | assert self.db.BlogPost.find().count() > 0 122 | rec_post = self.db.BlogPost.find_one({'title': u"Flask-MongoKit"}) 123 | assert rec_post.title == post.title 124 | assert rec_post.body == rec_post.body 125 | assert rec_post.author == rec_post.author 126 | 127 | def test_get_or_404(self): 128 | self.db.register([BlogPost]) 129 | 130 | assert len(self.db.registered_documents) > 0 131 | assert self.db.registered_documents[0] == BlogPost 132 | 133 | post = self.db.BlogPost() 134 | post.title = u"Flask-MongoKit" 135 | post.body = u"Flask-MongoKit is a layer between Flask and MongoKit" 136 | post.author = u"Christoph Heer" 137 | post.save() 138 | 139 | assert self.db.BlogPost.find().count() > 0 140 | assert "get_or_404" in dir(self.db.BlogPost) 141 | try: 142 | self.db.BlogPost.get_or_404(post['_id']) 143 | except NotFound: 144 | self.fail("There should be a document with this id") 145 | self.assertRaises(NotFound, self.db.BlogPost.get_or_404, ObjectId()) 146 | 147 | def test_find_one_or_404(self): 148 | self.db.register([BlogPost]) 149 | 150 | assert len(self.db.registered_documents) > 0 151 | assert self.db.registered_documents[0] == BlogPost 152 | 153 | post = self.db.BlogPost() 154 | post.title = u"Flask-MongoKit" 155 | post.body = u"Flask-MongoKit is a layer between Flask and MongoKit" 156 | post.author = u"Christoph Heer" 157 | post.save() 158 | 159 | assert self.db.BlogPost.find().count() > 0 160 | assert "find_one_or_404" in dir(self.db.BlogPost) 161 | try: 162 | self.db.BlogPost.find_one_or_404({'title': u'Flask-MongoKit'}) 163 | except NotFound: 164 | self.fail("There should be a document with this title") 165 | self.assertRaises(NotFound, self.db.BlogPost.find_one_or_404, 166 | {'title': u'Flask is great'}) 167 | 168 | class BaseTestCaseWithAuth(): 169 | def setUp(self): 170 | db = 'flask_testing_auth' 171 | conn = Connection() 172 | conn[db].add_user('test', 'test') 173 | 174 | self.app = create_app() 175 | self.app.config['TESTING'] = True 176 | self.app.config['MONGODB_DATABASE'] = db 177 | 178 | self.db = MongoKit(self.app) 179 | 180 | def test_correct_login(self): 181 | self.app.config['MONGODB_USERNAME'] = 'test' 182 | self.app.config['MONGODB_PASSWORD'] = 'test' 183 | 184 | self.db.connect() 185 | 186 | def test_incorrect_login(self): 187 | self.app.config['MONGODB_USERNAME'] = 'fuu' 188 | self.app.config['MONGODB_PASSWORD'] = 'baa' 189 | 190 | self.assertRaises(AuthenticationIncorrect, self.db.connect) 191 | 192 | class BaseTestCaseMultipleApps(): 193 | 194 | def setUp(self): 195 | self.app_1 = create_app() 196 | self.app_1.config['MONGODB_DATABASE'] = 'app_1' 197 | 198 | self.app_2 = create_app() 199 | self.app_2.config['MONGODB_DATABASE'] = 'app_2' 200 | 201 | assert self.app_1 != self.app_2 202 | 203 | self.db = MongoKit() 204 | self.db.init_app(self.app_1) 205 | self.db.init_app(self.app_2) 206 | 207 | def tearDown(self): 208 | self.pop_ctx() 209 | 210 | def push_ctx(self): 211 | raise NotImplementedError 212 | 213 | def pop_ctx(self): 214 | raise NotImplementedError 215 | 216 | def test_app_1(self): 217 | self.push_ctx(self.app_1) 218 | 219 | self.db.connect() 220 | assert self.db.connected 221 | assert self.db.name == 'app_1' 222 | assert self.db.name != 'app_2' 223 | 224 | def test_app_2(self): 225 | self.push_ctx(self.app_2) 226 | 227 | self.db.connect() 228 | assert self.db.connected 229 | assert self.db.name != 'app_1' 230 | assert self.db.name == 'app_2' 231 | 232 | class TestCaseInitAppWithRequestContext(BaseTestCaseInitAppWithContext, unittest.TestCase): 233 | def setUp(self): 234 | self.app = create_app() 235 | 236 | self.ctx = self.app.test_request_context('/') 237 | self.ctx.push() 238 | 239 | def tearDown(self): 240 | self.ctx.pop() 241 | 242 | class TestCaseWithRequestContext(BaseTestCaseWithContext, unittest.TestCase): 243 | def setUp(self): 244 | self.app = create_app() 245 | self.db = MongoKit(self.app) 246 | 247 | self.ctx = self.app.test_request_context('/') 248 | self.ctx.push() 249 | 250 | def tearDown(self): 251 | self.ctx.pop() 252 | 253 | class TestCaseWithRequestContextAuth(BaseTestCaseWithAuth, unittest.TestCase): 254 | def setUp(self): 255 | super(TestCaseWithRequestContextAuth, self).setUp() 256 | 257 | self.ctx = self.app.test_request_context('/') 258 | self.ctx.push() 259 | 260 | def tearDown(self): 261 | self.ctx.pop() 262 | 263 | class TestCaseMultipleAppsWithRequestContext(BaseTestCaseMultipleApps, unittest.TestCase): 264 | def push_ctx(self, app): 265 | self.ctx = app.test_request_context('/') 266 | self.ctx.push() 267 | 268 | def tearDown(self): 269 | self.ctx.pop() 270 | 271 | # Only testing is the flask version support app context (since flask v0.9) 272 | if hasattr(Flask, "app_context"): 273 | class TestCaseInitAppWithAppContext(BaseTestCaseInitAppWithContext, unittest.TestCase): 274 | def setUp(self): 275 | self.app = create_app() 276 | 277 | self.ctx = self.app.app_context() 278 | self.ctx.push() 279 | 280 | def tearDown(self): 281 | self.ctx.pop() 282 | 283 | class TestCaseWithAppContext(BaseTestCaseWithContext, unittest.TestCase): 284 | def setUp(self): 285 | self.app = create_app() 286 | self.db = MongoKit(self.app) 287 | 288 | self.ctx = self.app.app_context() 289 | self.ctx.push() 290 | 291 | def tearDown(self): 292 | self.ctx.pop() 293 | 294 | class TestCaseWithAppContextAuth(BaseTestCaseWithAuth, unittest.TestCase): 295 | def setUp(self): 296 | super(TestCaseWithAppContextAuth, self).setUp() 297 | 298 | self.ctx = self.app.app_context() 299 | self.ctx.push() 300 | 301 | def tearDown(self): 302 | self.ctx.pop() 303 | 304 | class TestCaseMultipleAppsWithAppContext(BaseTestCaseMultipleApps, unittest.TestCase): 305 | def push_ctx(self, app): 306 | self.ctx = app.app_context() 307 | self.ctx.push() 308 | 309 | def tearDown(self): 310 | self.ctx.pop() 311 | 312 | if __name__ == '__main__': 313 | unittest.main() 314 | --------------------------------------------------------------------------------