├── .gitignore ├── README ├── flask.wsgi ├── models.py ├── myapp.py ├── settings.py ├── static └── style.css ├── templates ├── base.html ├── index.html ├── login.html ├── record.html └── users.html └── tests.py /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | *.pyc 3 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | A blank Flask app template using MongoDB. 2 | 3 | Requirements: 4 | * Python 5 | * MongoDB 6 | * Flask Framework http://flask.pocoo.org 7 | * PyMongo (pip install pymongo==2.8) 8 | * MongoEngine http://mongoengine.org 9 | * Flask Bcrypt extension for encrypting your login passwords (pip install flask-bcrypt) 10 | * Flash CSRF extension for protecting you app against cross-site forgery (pip install flask-csrf) 11 | * Apache + mod_wsgi (optional) 12 | 13 | Initial data: 14 | * To use this app you first need to enter some data [manually] into MongoDB for Post model using the "tumblelog" database (see models.py). 15 | * You will also need to create a user if you want to use the login/logout views. Create the user manually and use python's bcrypt module to create a password. 16 | -------------------------------------------------------------------------------- /flask.wsgi: -------------------------------------------------------------------------------- 1 | import sys 2 | flaskfirst = "/mnt/hgfs/winwww/flaskr" 3 | if not flaskfirst in sys.path: 4 | sys.path.insert(0, flaskfirst) 5 | 6 | sys.stdout = sys.stderr 7 | 8 | from myapp import app 9 | application = app 10 | -------------------------------------------------------------------------------- /models.py: -------------------------------------------------------------------------------- 1 | from mongoengine import * 2 | 3 | connect('tumblelog') 4 | 5 | class User(Document): 6 | email = StringField(required=True) 7 | first_name = StringField(max_length=50) 8 | last_name = StringField(max_length=50) 9 | password = StringField(max_length=200) 10 | 11 | class Comment(EmbeddedDocument): 12 | content = StringField() 13 | name = StringField(max_length=120) 14 | 15 | class Post(Document): 16 | title = StringField(max_length=120, required=True) 17 | author = ReferenceField(User) 18 | tags = ListField(StringField(max_length=30)) 19 | comments = ListField(EmbeddedDocumentField(Comment)) 20 | meta = {'allow_inheritance': True} 21 | 22 | class TextPost(Post): 23 | content = StringField() 24 | 25 | class ImagePost(Post): 26 | image_path = StringField() 27 | 28 | class LinkPost(Post): 29 | link_url = StringField() 30 | 31 | -------------------------------------------------------------------------------- /myapp.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, request, session, g, redirect, url_for, abort, render_template, flash 2 | from models import * 3 | from flask.ext.bcrypt import Bcrypt 4 | from flask.ext.csrf import csrf 5 | import logging 6 | 7 | app = Flask(__name__) 8 | app.config.from_object('settings') 9 | bcrypt = Bcrypt(app) 10 | csrf(app) 11 | 12 | @app.route('/') 13 | def index(): 14 | posts = Post.objects.all() 15 | return render_template('index.html', p=posts) 16 | 17 | @app.route('/record//') 18 | def record(id): 19 | post = Post.objects.get(id=id) 20 | return render_template('record.html', p=post) 21 | 22 | @app.route('/users/') 23 | def users(): 24 | users = User.objects.all() 25 | return render_template('users.html', u=users) 26 | 27 | @app.route('/login', methods=['GET', 'POST']) 28 | def login(): 29 | error = None 30 | if request.method == 'POST': 31 | try: 32 | this_user = User.objects.get(email=request.form['username']) 33 | if request.form['username'] != this_user.email: 34 | error = 'Invalid username' 35 | elif bcrypt.check_password_hash(this_user.password, request.form['password']) == False: 36 | error = 'Invalid password' 37 | else: 38 | session['logged_in'] = True 39 | session['this_user'] = {'first_name':this_user.first_name} 40 | 41 | flash('You were logged in') 42 | return redirect(url_for('index')) 43 | except: 44 | flash('User does not exist') 45 | return render_template('login.html', error=error) 46 | 47 | @app.route('/logout') 48 | def logout(): 49 | session.pop('logged_in', None) 50 | flash('You were logged out') 51 | return redirect(url_for('index')) 52 | 53 | if __name__ == '__main__': 54 | app.debug = app.config['DEBUG'] 55 | app.run() 56 | -------------------------------------------------------------------------------- /settings.py: -------------------------------------------------------------------------------- 1 | DEBUG = True 2 | 3 | SECRET_KEY = 'sdfsdf82347$$%$%$%$&fsdfs!!ASx+__WEBB$' 4 | -------------------------------------------------------------------------------- /static/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: arial; 3 | color: #333; 4 | } 5 | 6 | a { 7 | color: #333; 8 | text-decoration: underline; 9 | } 10 | 11 | a:hover { 12 | color: #999; 13 | text-decoration: none; 14 | } 15 | 16 | .metanav { 17 | background-color: #ddd; 18 | padding: 10px; 19 | } 20 | 21 | #main_content { 22 | margin: 10px; 23 | } 24 | 25 | .flash { 26 | color: red; 27 | } -------------------------------------------------------------------------------- /templates/base.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | Flask test 6 | 7 | 8 | 9 | 10 | {% for message in get_flashed_messages() %} 11 |
{{ message }}
12 | {% endfor %} 13 | 14 |
15 | Home | 16 | {% if not session.logged_in %} 17 | log in 18 | {% else %} 19 | Logged in as {{ session.this_user.first_name }} log out 20 | {% endif %} 21 |
22 | 23 |
24 | {% block body %}{% endblock %} 25 |
26 | 27 | 28 | -------------------------------------------------------------------------------- /templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block body %} 4 |

Posts

5 | 6 | 11 | 12 | {% endblock %} 13 | -------------------------------------------------------------------------------- /templates/login.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block body %} 4 | 5 |

Login

6 | {% if error %}

Error: {{ error }}{% endif %} 7 |

8 | 9 |
10 |
Username: 11 |
12 |
Password: 13 |
14 |
15 |
16 |
17 | 18 | {% endblock %} -------------------------------------------------------------------------------- /templates/record.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block body %} 4 | 5 | {{ p.title }} 6 | 7 | {% endblock %} 8 | -------------------------------------------------------------------------------- /templates/users.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block body %} 4 | 5 | 10 | 11 | {% endblock %} -------------------------------------------------------------------------------- /tests.py: -------------------------------------------------------------------------------- 1 | import os 2 | import myapp 3 | import unittest 4 | import tempfile 5 | 6 | class MyappTestCase(unittest.TestCase): 7 | 8 | def setUp(self): 9 | myapp.app.config['DEBUG'] = tempfile.mkstemp() 10 | self.app = myapp.app.test_client() 11 | 12 | def tearDown(self): 13 | pass 14 | 15 | def test_index(self): 16 | rv = self.app.get('/') 17 | assert '

Posts

' in rv.data 18 | 19 | if __name__ == '__main__': 20 | unittest.main() --------------------------------------------------------------------------------