65
loading...
This website collects cookies to deliver better user experience
git clone https://github.com/garutilorenzo/simple-bottlepy-application.git
cd simple-bottlepy-application
ln -s docker-compose-dev.yml docker-compose.yml
ln -s docker-compose-dev.yml docker-compose.yml
Prod | Dev |
---|---|
Nginx is used to expose our example application | Built-in HTTP development server |
Http port 80 | Http port 8080 |
Debug mode is disabled | Debug mode is enabled |
Reloader is disabled | Reloader is enabled |
./download_samples.sh
for sample in workplace.meta.stackexchange.com.7z unix.meta.stackexchange.com.7z
for sample in workplace.stackexchange.com.7z unix.stackexchange.com.7z
class Sites(enum.Enum):
vi = 'vi.stackexchange.com'
workplace = 'workplace.stackexchange.com'
wordpress = 'wordpress.stackexchange.com'
unix = 'unix.stackexchange.com'
tex = 'tex.stackexchange.com'
docker-compose run --rm bottle bash
web@4edf053b7e4f:~/src$ python init_db.py # <- Initialize DB
web@4edf053b7e4f:~/src$ python import_data.py # <- Import sample data
docker-compose up -d
Creating network "bottle-exchange_default" with the default driver
Creating postgres ... done
Creating redis ... done
Creating bottle ... done
curl --header "Content-Type: application/json" \
--request POST \
--data '{"auth_key":"dd4d5ff1c13!28356236c402d7ada.aed8b797ebd299b942291bc66,f804492be2009f14"}' \
http://localhost:8080/api/get/tags | jq
{
"data": [
{
"clean_name": "html5",
"created_time": "2021-12-29 11:33:06.517152+00:00",
"id": "1",
"name": "html5",
"network_sites": "Sites.wordpress",
"questions": "91",
"tag_id": "2",
"updated_time": "None"
},
...
],
"errors": [],
"items": 5431,
"last_page": 27
}
/app/src/<BOTTLE_APP_NAME>/config/<BOTTLE_APP_ENVIRONMENT>
---
enable_debug: True
enable_reloader: True
http_port: 8080
pgsql_username: "bottle"
pgsql_password: "b0tTl3_Be#"
pgsql_db: "bottle_exchange"
pgsql_host: "pgsql"
pgsql_port: 5432
create_db_schema: True
default_result_limit: 50
import load_config # <- See App configuration
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
main_config = load_config.load_config()
conn_string = 'postgresql+psycopg2://{pgsql_username}:{pgsql_password}@{pgsql_host}:{pgsql_port}/{pgsql_db}'.format(**main_config)
engine = create_engine(conn_string, pool_size=80, pool_recycle=60)
Session = sessionmaker(bind=engine)
Base = declarative_base()
schema | Tables | Description |
---|---|---|
network.py |
None | Sites class is not a SQLAlchemy object, but is an Enum used by all the other tables |
posts.py |
posts,post_history | Table definition for post and post_history tables. This module contains also three enum definitions: PostType, PostHistoryType, CloseReason |
tags.py |
tags | Tags table |
users.py |
users | Users table |
from schema.base import Base, engine # <- Base and engine are defined in the schema module, see "DB configuration"
from bottle_sa import SQLAlchemyPlugin
import load_config
main_config = load_config.load_config()
# Main Bottle app/application
app = application = Bottle()
# DB Plugin
saPlugin = SQLAlchemyPlugin(
engine=engine, metadata=Base.metadata,
create=main_config['create_db_schema'],
config=main_config,
)
application.install(saPlugin)
@app.route('/docs')
@view('docs')
def index(db): # <- db is our SQLAlchemy session
return dict(page_name='docs')
from bottle_cache import RedisCache
# Cache
cache = RedisCache()
@app.route('/tags')
@app.route('/tags/<page_nr:int>')
@cache.cached()
@view('tags')
def get_tags(db, page_nr=1):
do_something()
return something
config = {'redis_host': '<redis_hostname'>, 'redis_port': 6379, 'redis_db': 0, 'cache_expiry': 86400}
cache = RedisCache(config=config)
Param | Default | Description |
---|---|---|
redis_host |
redis |
Redis FQDN or ip address |
redis_port |
6379 |
Redis listen port |
redis_db |
0 |
Redis database |
cache_expiry |
3600 |
Global cache expiry time in seconds |
Param | Default | Description |
---|---|---|
expiry |
None |
Route cache expiry time. If not defined is the same value as the global expiry time |
key_prefix |
bottle_cache_%s |
Redis key prefix |
content_type |
text/html; charset=UTF-8 |
Default content type |
@app.route('/api/get/tags', method='POST')
@cache.cached(content_type='application/json')
def api_get_tags(db):
do_something()
return something
./dump_db.sh
volumes:
- type: volume
source: postgres
target: /var/lib/postgresql/data
- ./sql:/docker-entrypoint-initdb.d # <- uncomment this line
docker-compose down
Stopping bottle ... done
Stopping postgres ... done
Stopping redis ... done
Removing bottle ... done
Removing postgres ... done
Removing redis ... done
Removing network bottle-exchange_default