Skip to content

arun-n-a/flask-bp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 

Repository files navigation

flask-bp

Boilerplate for Flask

Pre-requirement:

python 3.7.4 pipenv

Step1: Create project directory named "flask-bf"

      mkdir flask-bf
      cd flask-bf

Step2: Install flask using pipenv

    pipenv shell
    pipenv install flask

Now the directory looks like

. ├── Pipfile └── Pipfile.lock Step3: Create a package called "app" inside flask-bp directory

  mkdir app
  cd app

Step4: Inside app directory create a file named init.py and save the below code. Next you have to change the url_prefix value '/boilerplate/v1' as required in the endpoints.

# flask-bp/app/__init__.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from config import Config
from flask_cors import CORS

db = SQLAlchemy()
migrate = Migrate()


def create_app(config_class=Config):
    app = Flask(__name__)
    app.config.from_object(config_class)
    CORS(app)

    db.init_app(app)
    migrate.init_app(app, db)

    from app.api import bp as api_bp
    app.register_blueprint(api_bp, url_prefix='/boilerplate/v1')

    return app

from app import models

Step5: Install the packages which are used in step4.

    pipenv install flask-sqlalchemy
    pipenv install flask-migrate
    pipenv install Migrate
    pipenv install flask-cors
    pipenv install python-dotenv
    pipenv install Flask-HTTPAuth

Step6: Create "config.py" in root directory. To store the configuration datas.

        cd ..
        touch config.py

Append the below mentioned code into the config.py file.

  ~/flask-bp/config.py
  import os
  from dotenv import load_dotenv

  basedir = os.path.abspath(os.path.dirname(__file__))
  load_dotenv(os.path.join(basedir, '.env'))


  class Config(object):
      DEBUG = os.environ.get('DEBUG') or False
      SECRET_KEY = os.environ.get('SECRET_KEY') or "ACSGSUGQJKDQTVDVQIIUDVBCREQVXPOOHKBEQMNFEIKVXH"
      PASSWORD_RESET_SALT = os.environ.get('PASSWORD_RESET_SALT') or "GFVDHWBIJBCWHBCHBIHCJJWccFWEF"
      PORT = os.environ.get('PORT') or 5000
      SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or \
          'sqlite:///' + os.path.join(basedir, 'app.db')
      SQLALCHEMY_TRACK_MODIFICATIONS = False
      PER_PAGE = os.environ.get('PER_PAGE')
      # S3_BUCKET = os.environ.get('S3_BUCKET')
      # AWS_ACCESS_KEY_ID = os.environ.get('AWS_ACCESS_KEY_ID')
      # AWS_SECRET_ACCESS_KEY = os.environ.get('AWS_SECRET_ACCESS_KEY')
      # SENDGRID_API_KEY = os.environ.get('SENDGRID_API_KEY')
      # STRIPE_SECRET_KEY = os.environ.get('STRIPE_SECRET_KEY')

Step7: Create a file runserver.py in the root directory and append the code. Import all models and return in make_shell_context()

    ~/flask-bp/runserver.py
    
    from app import create_app, db
    from app.models import Users, 

    app = create_app()


    @app.shell_context_processor
    def make_shell_context():
        return {'db': db, 'Users': Users, 'key': 'value'}


    if __name__ == "__main__":
        # import ptvsd
        # address = ('0.0.0.0', 3000)
        # ptvsd.enable_attach(address)
        app.run(host='0.0.0.0', debug=app.config["DEBUG"], port=app.config["PORT"])

Now the directory looks like:

  .
├── app
│   └── __init__.py
├── config.py
├── Pipfile
├── Pipfile.lock
└── runserver.py

Step10: Make three folders inside the folder "app", "models" to add all models, "services" to add all logical side functions and "api" to have all api routes in single folder.

    cd app/
    mkdir api
    mkdir models
    mkdir services

Now the directory looks like:

├── app
│   ├── api
│   ├── __init__.py
│   ├── models
│   └── services
├── config.py
├── Pipfile
├── Pipfile.lock
└── runserver.py

Step11: Inside these 3 folders create an empty file "init.py". Later all the files inside each folders should be added in the corresponding init.py file. Create another folder "templates" to store template files, here init.py is not required.

Now the directory looks like:

.
├── app
│   ├── api
│   │   └── __init__.py
│   ├── __init__.py
│   ├── models
│   │   └── __init__.py
│   └── services
│   │  └── __init__.py
│   └── templates
├── config.py
├── Pipfile
├── Pipfile.lock
└── runserver.py

Step12: Next lets create models.

    cd models

First create a file "base.py" which can be used by any other models. Inside the base class default created and updated columns are added, get all datas from a model and return the result in pagination form as dict.

# ~/flask-bp/app/models/base.py

from app import db
from config import Config


class BaseModel(db.Model):
    __abstract__ = True
    created = db.Column(db.DateTime, default=db.func.now())
    updated = db.Column(db.DateTime, default=db.func.now(), onupdate=db.func.now())

    @classmethod
    def to_collection_dict(cls, url, page=1, per_page=20, **kwargs):
        resources = cls.query.paginate(page, per_page, False)
        data = {
            'item': [item.to_dict() for item in resources.items],
            '_meta': {
                'page': page,
                'per_page': per_page,
                'total_pages': resources.pages,
                'total_items': resources.total,
                'url': Config.BASE_URL + url
            }

        }
        return {"status": 200, "message": "success", "data": data.get('item', ""), "_meta": data.get('_meta', "")}, True

    def to_dict(self):
        pass

Next create a users model "users.py" inside the directory models itself

# ~/flask-bp/app/models/users.py
from app import db
from config import Config
from werkzeug.security import generate_password_hash, check_password_hash
from flask_httpauth import HTTPBasicAuth
from itsdangerous import (TimedJSONWebSignatureSerializer
                          as Serializer, BadSignature, SignatureExpired)
from app.models import BaseModel
from app.constants import Access

auth = HTTPBasicAuth()

class Users(BaseModel):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    email = db.Column(db.String(128), index=True, unique=True)
    first_name = db.Column(db.String(128))
    last_name = db.Column(db.String(64))
    phone = db.Column(db.String(15))
    password = db.Column(db.String(128))
    auth_token = db.Column(db.String(300))
    #address1 = db.Column(db.String(128))
    #address2 = db.Column(db.String(128))
    #state = db.Column(db.String(64))
    #country = db.Column(db.String(64))
    #zipcode = db.Column(db.Integer)
    #status = db.Column(db.Boolean)
    #role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))
    #token_expiration = db.Column(db.String(128))
    #orders = db.relationship('Orders', backref='user_order', lazy='dynamic')
    #transactions = db.relationship('Transactions', backref='user_transaction', lazy='dynamic')

    def to_dict(self):
        data = {
            'id': self.id,
            'user_id': self.id,
            'email': self.email,
            'first_name': self.first_name,
            'last_name': self.last_name,
            'name': ((self.first_name or ' ') + " " + (self.last_name or ' ')).strip(),
            'phone': self.phone,
            #'address': ((self.address1 or '') + ", " + (self.address2 or ' ')).strip(),
            #'country': self.country,
            #'zip': self.zipcode,
            #'role_id': self.role_id,
            'created': self.created.strftime('%Y-%m-%d %H:%M %p')
        }
        return data

    def get_hashed_password(self, password):
        return generate_password_hash(password)

    def hash_password(self, password):
        self.password = generate_password_hash(password)

    def check_password(self, password):
        return check_password_hash(self.password, password)

    def generate_auth_token(self, expiration=600):
        s = Serializer(Config.SECRET_KEY, expires_in=expiration)
        return s.dumps({'id': self.id})

    def is_admin(self):
        return self.role_id == Access.ADMIN

    @staticmethod
    def verify_auth_token(token):
        s = Serializer(Config.SECRET_KEY)
        try:
            data = s.loads(token)
        except SignatureExpired:
            return None
        except BadSignature:
            return None
        user = Users.query.get(data['id'])
        return user

Step13: Now we had 2 models so next we need to add this in init.py of models.

        #~/flask-bp/app/models/__init__.py
        from app.models.base import BaseModel
        from app.models.users import Users
        
    Like this if we create new models then update it in the __init__.py file also.

Step14:

About

Boiler plate for Flask

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published