├── .gitignore ├── README.md ├── basesite ├── __init__.py ├── apis │ └── __init__.py ├── application.py ├── configs.py ├── helpers.py ├── models.py ├── static │ ├── css │ │ └── test.css │ ├── img │ │ └── test.jpg │ └── script │ │ └── test.js ├── templates │ └── test.html └── views │ ├── __init__.py │ └── test_view.py ├── manage.py ├── requirement.txt ├── supervisord.conf └── tests ├── __init__.py └── test_site.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[cod] 2 | 3 | # C extensions 4 | *.so 5 | 6 | # Packages 7 | *.egg 8 | *.egg-info 9 | dist 10 | build 11 | eggs 12 | parts 13 | bin 14 | var 15 | sdist 16 | develop-eggs 17 | .installed.cfg 18 | lib 19 | lib64 20 | 21 | # Installer logs 22 | pip-log.txt 23 | 24 | # Unit test / coverage reports 25 | .coverage 26 | .tox 27 | nosetests.xml 28 | 29 | # Translations 30 | *.mo 31 | 32 | # Mr Developer 33 | .mr.developer.cfg 34 | .project 35 | .pydevproject 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # flask-base 2 | 3 | a skeleton for flask 4 | 5 | author: notedit 6 | 7 | ### virtualenv+flask+gunicorn+supervisor环境搭建与部署 8 | 9 | 10 | 这个代码库包含了一个flask web站的基本框架,可以通过如下的步骤把一个生产环境搭建起来 11 | 12 | #### 新建一个用户 13 | 14 | 新建一个用户名wwwuser 所属wwwuser组的用户,具体的步骤可自行搜索 15 | 16 | #### 安装virtualenv和依赖 17 | 18 | ``` 19 | sudo pip install virtualenv 20 | sudo pip install virtualenvwrapper 21 | ``` 22 | 23 | 这样就安装好virtualenv 和 virtualenvwrapper,然后建立一个虚拟环境, 24 | 25 | ``` 26 | source /usr/local/bin/virtualenvwrapper.sh 27 | mkvirtualenv --no-site-packages online 28 | ``` 29 | 这样就建立了一个online的虚拟环境,为了以后不用每次都执行source /usr/local/bin/virtualenvwrapper.sh,可以把这行语句放到 ~/.bashrc 中去. 30 | 31 | 进入flask-base中,安装需要的依赖 32 | 33 | ``` 34 | pip install -r requirement.txt 35 | ``` 36 | 37 | #### 查看目录和运行单元测试 38 | 39 | 装完依赖之后就可以查看代码布局了,代码很简单,你可以在此基础上添加一些自己的东西. 40 | 41 | 在代码的根目录你可以看到一个manage.py,这个是整个代码的入口,你可以运行 42 | 43 | ``` 44 | python manage.py 45 | ``` 46 | 你可以添加自己想要的命令,比如新建用户,迁移一些数据等等. 47 | 48 | 还包含了一些测试代码,你可以在代码的根目录运行单元测试: 49 | 50 | ``` 51 | nosetest tests 52 | ``` 53 | 54 | #### supervisor 55 | 56 | 在正常的网站运行中,你需要一些进程管理工具,这里使用supervisor,代码库中已经包含一个 supervisord 的配置文件,你可以添加自己的服务. 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /basesite/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # author: notedit 4 | 5 | from basesite.application import create_app 6 | -------------------------------------------------------------------------------- /basesite/apis/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notedit/flask-base/057394cf23fd3c888a7290f3d84fc1f313af0457/basesite/apis/__init__.py -------------------------------------------------------------------------------- /basesite/application.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | import os 5 | import logging 6 | from flask import Flask 7 | 8 | from basesite import configs 9 | 10 | from basesite.views import test_view as test 11 | # add some other view 12 | 13 | __all__ = ['create_app'] 14 | 15 | 16 | DEFAULT_APP_NAME = 'basesite' 17 | 18 | REGISTER_BLUE_PRINTS = ( 19 | (test.instance,''), 20 | # add your blue print here 21 | ) 22 | 23 | def create_app(config=None,app_name=None): 24 | 25 | if app_name is None: 26 | app_name = DEFAULT_APP_NAME 27 | 28 | app = Flask(app_name) 29 | 30 | configure_app(app,config) 31 | #configure_db(app) 32 | configure_blueprints(app) 33 | #configure_cache(app) 34 | return app 35 | 36 | def configure_app(app,config): 37 | app.config.from_object(configs.DefaultConfig()) 38 | 39 | if config is not None: 40 | app.config.from_object(config) 41 | 42 | app.config.from_envvar('APP_CONFIG',silent=True) 43 | 44 | def configure_db(app): 45 | pass 46 | 47 | def configure_blueprints(app): 48 | for blue,url_prefix in REGISTER_BLUE_PRINTS: 49 | #app.register_blueprint(blue) 50 | app.register_blueprint(blue,url_prefix=url_prefix) 51 | 52 | 53 | -------------------------------------------------------------------------------- /basesite/configs.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import datetime 4 | 5 | class DefaultConfig(object): 6 | 7 | DEBUG = True 8 | SECRET_KEY = '' 9 | SESSION_COOKIE_PATH='/' 10 | SESSION_COOKIE_HTTPONLY = True 11 | SESSION_COOKIE_SECURE = True 12 | SESSION_COOKIE_NAME = 'Ssession' 13 | PERMANENT_SESSION_LIFETIME = datetime.timedelta(31) 14 | SQLALCHEMY_DATABASE_URL = 'postgresql+psycopg2://xxxxxxxxxxxxx' 15 | SQLALCHEMY_ECHO = False 16 | 17 | class TestConfig(object): 18 | SQLALCHEMY_DATABASE_URL = 'postgresql+psycopg2://xxxxxxxxxxxxxxxxx' 19 | SQLALCHEMY_ECHO = False 20 | 21 | class ProductionConfig(object): 22 | SQLALCHEMY_ECHO = False 23 | DEBUG = False 24 | 25 | -------------------------------------------------------------------------------- /basesite/helpers.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | # author: notedit 5 | -------------------------------------------------------------------------------- /basesite/models.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | # add your models here 5 | -------------------------------------------------------------------------------- /basesite/static/css/test.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notedit/flask-base/057394cf23fd3c888a7290f3d84fc1f313af0457/basesite/static/css/test.css -------------------------------------------------------------------------------- /basesite/static/img/test.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notedit/flask-base/057394cf23fd3c888a7290f3d84fc1f313af0457/basesite/static/img/test.jpg -------------------------------------------------------------------------------- /basesite/static/script/test.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notedit/flask-base/057394cf23fd3c888a7290f3d84fc1f313af0457/basesite/static/script/test.js -------------------------------------------------------------------------------- /basesite/templates/test.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notedit/flask-base/057394cf23fd3c888a7290f3d84fc1f313af0457/basesite/templates/test.html -------------------------------------------------------------------------------- /basesite/views/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notedit/flask-base/057394cf23fd3c888a7290f3d84fc1f313af0457/basesite/views/__init__.py -------------------------------------------------------------------------------- /basesite/views/test_view.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # author: notedit 4 | # date: 2012/12/01 morning 5 | 6 | import sys 7 | import time 8 | import flask 9 | from flask import Blueprint 10 | from flask import request 11 | from flask import g 12 | from flask import Response 13 | from flask import current_app 14 | from flask import session 15 | from flask import jsonify 16 | from flask.views import MethodView 17 | from flask.views import View 18 | 19 | 20 | instance = Blueprint('index',__name__) 21 | 22 | class TestView(MethodView): 23 | def get(self): 24 | return jsonify(hello="""do not panic""") 25 | 26 | instance.add_url_rule('/test',view_func=TestView.as_view('test'),methods=['GET',]) 27 | -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # author: notedit 3 | 4 | import os 5 | import sys 6 | from flask import current_app 7 | from flask.ext.script import Manager,prompt,prompt_pass,\ 8 | prompt_bool,prompt_choices 9 | from flask.ext.script import Server 10 | 11 | from basesite import create_app 12 | 13 | manager = Manager(create_app) 14 | app = create_app 15 | 16 | @manager.command 17 | def initdb(): 18 | if prompt_bool("Are you sure? You will init your database"): 19 | pass 20 | 21 | @manager.command 22 | def dropdb(): 23 | if prompt_bool("Are you sure? You will lose all your data!"): 24 | pass 25 | 26 | @manager.option('-u','--username',dest='username',required=True) 27 | @manager.option('-p','--password',dest='password',required=True) 28 | @manager.option('-e','--email',dest='email',required=True) 29 | def createuser(username=None,password=None,email=None): 30 | pass 31 | 32 | manager.add_command('runserver',Server()) 33 | 34 | if __name__ == '__main__': 35 | manager.run() 36 | -------------------------------------------------------------------------------- /requirement.txt: -------------------------------------------------------------------------------- 1 | Flask==0.9 2 | Flask-Cache==0.6.0 3 | Flask-Script==0.3.3 4 | Jinja2==2.6 5 | SQLAlchemy==0.7.8 6 | WTForms==1.0.1 7 | Werkzeug==0.8.3 8 | colander==0.9.8 9 | gunicorn==0.15.0 10 | nose==1.2.1 11 | requests==0.14.1 12 | rq==0.3.2 13 | supervisor==3.0b1 14 | -------------------------------------------------------------------------------- /supervisord.conf: -------------------------------------------------------------------------------- 1 | [unix_http_server] 2 | file=/tmp/supervisord.sock 3 | chmod=0755 4 | chown=wwwuser:wwwuser 5 | 6 | [rpcinterface:supervisor] 7 | supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface 8 | 9 | [supervisord] 10 | logfile=/var/log/supervisord/supervisord.log 11 | logfile_maxbytes=10MB 12 | logfile_backups=10 13 | loglevel=info 14 | childlogdir=/var/log/supervisord/ 15 | pidfile=/var/run/supervisord.pid 16 | user=root 17 | 18 | [supervisorctl] 19 | serverurl=unix:///tmp/supervisord.sock 20 | 21 | [program:flask-base] 22 | command=gunicorn -w 4 -b 127.0.0.1:6000 manage:app 23 | process_name=%(program_name)s 24 | numprocs=1 25 | directory= xxxxx path to flask-base xxxxxxx 26 | autostart=true 27 | user=wwwuser 28 | stdout_logfile=/var/log/supervisord/flask-base-out.log 29 | stdout_logfile_maxbytes=1MB 30 | stdout_logfile_backups=10 31 | stderr_logfile=/var/log/supervisord/flask-base-err.log 32 | stderr_logfile_maxbytes=1MB 33 | stderr_logfile_backups=10 34 | 35 | 36 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import unittest 4 | 5 | from basesite import create_app 6 | from basesite import configs 7 | 8 | class TestCase(unittest.TestCase): 9 | 10 | def __init__(self,*args,**kwargs): 11 | self.app = create_app(configs.TestConfig) 12 | self.app.config['TESTING'] = True 13 | super(TestCase,self).__init__(*args,**kwargs) 14 | 15 | def setUp(self): 16 | self.client = self.app.test_client() 17 | print '不写单元测试的人注定一辈子敲代码' 18 | pass 19 | 20 | def tearDown(self): 21 | print 'hello world, do not panic' 22 | pass 23 | -------------------------------------------------------------------------------- /tests/test_site.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import json 4 | from tests import TestCase 5 | 6 | 7 | class TestSite(TestCase): 8 | 9 | def test_site(self): 10 | 11 | resp = self.client.get('/test') 12 | res = json.loads(resp.data) 13 | assert res['hello'] == """do not panic""" 14 | 15 | 16 | 17 | 18 | --------------------------------------------------------------------------------