├── Procfile ├── static ├── banner.png ├── demo.png ├── favicon.ico ├── css │ └── style.css └── js │ └── main.js ├── requirements.txt ├── .gitattributes ├── README.md ├── .gitignore ├── app.py └── templates └── index.html /Procfile: -------------------------------------------------------------------------------- 1 | web: gunicorn -k gevent app:app 2 | -------------------------------------------------------------------------------- /static/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helloflask/calculator/master/static/banner.png -------------------------------------------------------------------------------- /static/demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helloflask/calculator/master/static/demo.png -------------------------------------------------------------------------------- /static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helloflask/calculator/master/static/favicon.ico -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Flask==0.12.2 2 | Jinja2==2.8 3 | Werkzeug==0.13 4 | # deploy 5 | gunicorn==19.5.0 6 | gevent 7 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Calculator3 2 | A simple calculator made with Flask and JavaScript. 3 | 4 | ## DEMO 5 | https://greyli.github.io/calculator/ 6 | 7 |  8 | 9 | ## Versions 10 | Flask==0.11.1 11 | Jinja2==2.8 12 | Werkzeug==0.11.11 13 | 14 | ## Installation 15 | Change to app directory, use `virtualenv` create and activate virtual enviroment. 16 | Then use `pip` to install requirements: 17 | ``` 18 | pip install flask 19 | ``` 20 | Run: 21 | ``` 22 | set FLASK_APP=app.py 23 | flask run 24 | ``` 25 | 26 | Go to http://127.0.0.1:5000/ 27 | 28 | ## More details 29 | 关于这个项目的详细介绍:[Flask实践:计算器](https://zhuanlan.zhihu.com/p/24120882) 30 | 更多关于Flask的原创优质内容,欢迎关注[Hello, Flask!——知乎专栏](https://zhuanlan.zhihu.com/flask) 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear in the root of a volume 35 | .DocumentRevisions-V100 36 | .fseventsd 37 | .Spotlight-V100 38 | .TemporaryItems 39 | .Trashes 40 | .VolumeIcon.icns 41 | 42 | # Directories potentially created on remote AFP share 43 | .AppleDB 44 | .AppleDesktop 45 | Network Trash Folder 46 | Temporary Items 47 | .apdisk 48 | 49 | # Python 50 | __pycache__ 51 | *.pyc 52 | venv 53 | env 54 | -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Calculator 4 | ~~~~~~~~~~~~~~ 5 | 6 | A simple Calculator made by Flask and jQuery. 7 | 8 | :copyright: (c) 2015 by Grey li. 9 | :license: MIT, see LICENSE for more details. 10 | """ 11 | import re 12 | from flask import Flask, jsonify, render_template, request 13 | 14 | 15 | app = Flask(__name__) 16 | 17 | 18 | @app.route('/_calculate') 19 | def calculate(): 20 | a = request.args.get('number1', '0') 21 | operator = request.args.get('operator', '+') 22 | b = request.args.get('number2', '0') 23 | # validate the input data 24 | m = re.match(r'^\-?\d*[.]?\d*$', a) 25 | n = re.match(r'^\-?\d*[.]?\d*$', b) 26 | 27 | if m is None or n is None or operator not in '+-*/': 28 | return jsonify(result='Error!') 29 | 30 | if operator == '/': 31 | result = eval(a + operator + str(float(b))) 32 | else: 33 | result = eval(a + operator + b) 34 | return jsonify(result=result) 35 | 36 | 37 | @app.route('/') 38 | def index(): 39 | return render_template('index.html') 40 | 41 | 42 | if __name__ == '__main__': 43 | app.run(debug=True) 44 | -------------------------------------------------------------------------------- /static/css/style.css: -------------------------------------------------------------------------------- 1 | .box { 2 | font-family: 'Orbitron', sans-serif; 3 | width: 285px; 4 | height: 360px; 5 | margin: 15% auto auto; 6 | border: 1px solid #9e9b97; 7 | box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), inset -1px -6px 12px 0.1px #89847e; 8 | border-radius: 20px; 9 | -webkit-user-select: none; 10 | -moz-user-select: none; 11 | -ms-user-select: none; 12 | user-select: none; 13 | } 14 | 15 | .screen { 16 | height: 60px; 17 | width: 240px; 18 | border: 1px solid #7c877f; 19 | background: #c7d3c5; 20 | margin: 25px 20px 5px 20px; 21 | border-radius: 6px; 22 | } 23 | 24 | .main-screen { 25 | width: 240px; 26 | height: 22px; 27 | padding: 10px 5px; 28 | font-size: 20px; 29 | text-align: right; 30 | } 31 | 32 | .sub-screen { 33 | max-width: 280px; 34 | height: 15px; 35 | padding: 10px 5px; 36 | font-size: 12px; 37 | text-align: right; 38 | } 39 | 40 | .buttons { 41 | margin: 10px auto; 42 | } 43 | 44 | button { 45 | margin: 5px; 46 | padding: 3px 10px; 47 | width: 50px; 48 | height: 30px; 49 | border: none; 50 | box-shadow: 1px 2px #666; 51 | } 52 | 53 | button:focus {outline:0 !important;} 54 | 55 | button:active { 56 | box-shadow: none; 57 | transform: translateY(4px); 58 | } 59 | 60 | .btn-zero { 61 | width: 113px; 62 | margin-right: 7px; 63 | } 64 | 65 | .btn-equal { 66 | position: absolute; 67 | margin-left: 10px; 68 | height: 75px; 69 | } 70 | 71 | footer { 72 | font-size: 10px; 73 | } 74 | 75 | @media (max-width: 425px) { 76 | .github { 77 | display: none; 78 | } 79 | } -------------------------------------------------------------------------------- /templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |