Skip to main content

Flask

Flask is a lightweight, flexible Python Web framework with simplicity and scalability as its core design philosophy. It does not enforce dependencies on specific libraries or architectures, only providing core features such as routing and template rendering. Developers can freely choose components like databases and form validation. This "micro-framework" characteristic makes it extremely easy to learn, while enabling the easy construction of complex applications through extensions, making it particularly suitable for rapid development of small projects or as a foundation for microservices.

This guide describes how to deploy Flask applications on CloudBase HTTP cloud functions.

Prerequisites

Before you begin, ensure that you have:

  • Installed Python 3.10 or a later version
  • Have a Tencent Cloud account and have activated the CloudBase service
  • Have a basic knowledge of Python and Flask development

Step 1: Create a Flask Application

💡 Note: If you already have a Flask application, you can skip this step.

Create the project directory

mkdir flask-cloudbase
cd flask-cloudbase

Set up the virtual environment

# Create a virtual environment
python -m venv env

# Activate the virtual environment
# Linux/macOS
source env/bin/activate

# Windows
# env\Scripts\activate

Install Flask

pip install flask

Step 2: Write the Application Code

Create the app.py file as the entry file of the application:

⚠️ Important: CloudBase HTTP cloud functions require the application to listen on port 9000.

import os
from flask import Flask, jsonify, request

app = Flask(__name__)

# Configure the application
app.config['DEBUG'] = os.environ.get('DEBUG', 'False').lower() == 'true'
app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY', 'your-secret-key-here')

# Mock Data
users = [
{'id': 1, 'name': 'Zhang San', 'email': 'zhangsan@example.com'},
{'id': 2, 'name': 'Li Si', 'email': 'lisi@example.com'},
{'id': 3, 'name': 'Wang Wu', 'email': 'wangwu@example.com'}
]

@app.route('/')
def hello():
"""Root path handler function"""
return jsonify({
'message': 'Hello from Flask on CloudBase!',
'framework': 'Flask',
'version': '2.3.0'
})

@app.route('/health')
def health_check():
"""Health Check Endpoint"""
return jsonify({
'status': 'healthy',
'framework': 'Flask',
'python_version': os.sys.version
})

@app.route('/api/users', methods=['GET'])
def get_users():
"""Obtain user list (supports pagination)"""
page = request.args.get('page', 1, type=int)
limit = request.args.get('limit', 10, type=int)

# Simple Pagaging Logic
start_index = (page - 1) * limit
end_index = start_index + limit
paginated_users = users[start_index:end_index]

return jsonify({
'success': True,
'data': {
'total': len(users),
'page': page,
'limit': limit,
'items': paginated_users
}
})

@app.route('/api/users/<int:user_id>', methods=['GET'])
def get_user(user_id):
"""Obtain user by ID"""
user = next((u for u in users if u['id'] == user_id), None)
if not user:
return jsonify({
'success': False,
'message': 'User not found'
}), 404

return jsonify({
'success': True,
'data': user
})

@app.route('/api/users', methods=['POST'])
def create_user():
"""Create New User"""
data = request.get_json()

if not data or 'name' not in data or 'email' not in data:
return jsonify({
'success': False,
'message': 'Name and email are required'
}), 400

# Checking whether the email already exists
if any(u['email'] == data['email'] for u in users):
return jsonify({
'success': False,
'message': 'Email already exists'
}), 400

# Create New User
new_user = {
'id': max(u['id'] for u in users) + 1 if users else 1,
'name': data['name'],
'email': data['email']
}
users.append(new_user)

return jsonify({
'success': True,
'data': new_user
}), 201

@app.route('/api/users/<int:user_id>', methods=['PUT'])
def update_user(user_id):
"""Update User Information"""
user_index = next((i for i, u in enumerate(users) if u['id'] == user_id), None)
if user_index is None:
return jsonify({
'success': False,
'message': 'User not found'
}), 404

data = request.get_json()
if not data:
return jsonify({
'success': False,
'message': 'No data provided'
}), 400

# Check whether the email is already in use by another user
if 'email' in data and any(u['email'] == data['email'] and u['id'] != user_id for u in users):
return jsonify({
'success': False,
'message': 'Email already exists'
}), 400

# Update User Information
if 'name' in data:
users[user_index]['name'] = data['name']
if 'email' in data:
users[user_index]['email'] = data['email']

return jsonify({
'success': True,
'data': users[user_index]
})

@app.route('/api/users/<int:user_id>', methods=['DELETE'])
def delete_user(user_id):
"""Delete User"""
user_index = next((i for i, u in enumerate(users) if u['id'] == user_id), None)
if user_index is None:
return jsonify({
'success': False,
'message': 'User not found'
}), 404

deleted_user = users.pop(user_index)
return jsonify({
'success': True,
'message': f'User {deleted_user["name"]} deleted successfully'
})

# Error Handling
@app.errorhandler(404)
def not_found(error):
return jsonify({
'success': False,
'message': 'Resource not found'
}), 404

@app.errorhandler(500)
def internal_error(error):
return jsonify({
'success': False,
'message': 'Internal server error'
}), 500

@app.errorhandler(400)
def bad_request(error):
return jsonify({
'success': False,
'message': 'Bad request'
}), 400

if __name__ == '__main__':
# CloudBase HTTP cloud function requires listening on port 9000
app.run(host='0.0.0.0', port=9000, debug=False)

Code Explanation

Let's explain the key parts of the above code in detail:

  1. Flask Application Creation

    app = Flask(__name__)

    Create a Flask application instance; the __name__ parameter helps Flask identify the application's location.

  2. Route Decorator

    @app.route('/')
    def hello():
    return jsonify({'message': 'Hello from Flask!'})

    @app.route('/') decorator defines the URL route and executes the corresponding function when the root URL is accessed.

  3. HTTP Method Support

    @app.route('/api/users', methods=['GET', 'POST'])

    The HTTP methods supported by the route are specified via the methods parameter.

  4. Error Handling

    @app.errorhandler(404)
    def not_found(error):
    return jsonify({'error': 'Not Found'}), 404

    The @app.errorhandler decorator is used to handle specific HTTP errors.

Step 3: Local Testing

Starting Up the Application

python app.py

Testing API Endpoints

After the application starts up, you can test it in the following ways:

# Test the Root Path
curl http://localhost:9000/

# Test Health Check
curl http://localhost:9000/health

# Test User List
curl http://localhost:9000/api/users

# Test Pagination
curl "http://localhost:9000/api/users?page=1&limit=2"

# Test Obtaining a Single User
curl http://localhost:9000/api/users/1

# Test Creating a User
curl -X POST http://localhost:9000/api/users \
-H "Content-Type: application/json" \
-d '{"name":"New User","email":"newuser@example.com"}'

# Test Updating a User
curl -X PUT http://localhost:9000/api/users/1 \
-H "Content-Type: application/json" \
-d '{"name":"Updated User","email":"updated@example.com"}'

# Test Deleting a User
curl -X DELETE http://localhost:9000/api/users/1

Step 4: Configure Dependencies

Generate the requirements.txt file:

pip freeze > requirements.txt

⚠️ Note: It is only safe to run the above command in a virtual environment. Otherwise, it will generate all installed Python packages on the system, which may cause the cloud function to fail to start up properly.

Typical requirements.txt contents:

blinker==1.7.0
click==8.1.7
Flask==2.3.3
itsdangerous==2.1.2
Jinja2==3.1.2
MarkupSafe==2.1.3
Werkzeug==2.3.7

Step 5: Create the Startup Script

💡 Note:

  • When creating the scf_bootstrap file on windows, it is recommended to use
  • When creating the scf_bootstrap file using vscode on windows, deploying to an HTTP cloud function may result in an error: scf_bootstrap file does not exist
  • This error occurs because the script file contains Windows-style carriage returns (^M), causing Linux to fail to recognize the interpreter path correctly. This is a common issue in WSL

Create the scf_bootstrap file (with no extension):

#!/bin/bash
# Set the Python dependency loading path, which defaults to the third_party directory
export PYTHONPATH="./third_party:$PYTHONPATH"
/var/lang/python310/bin/python3.10 app.py

Grant execute permissions to the startup script:

chmod +x scf_bootstrap

💡 Note:

  • scf_bootstrap is the startup script for CloudBase cloud functions
  • Set the Python path and start the Flask application
  • Ensure the application listens on port 9000

Step 6: Prepare Deployment Files

Before deployment, install dependencies to the third_party directory:

⚠️ Note:

  • HTTP cloud functions do not automatically install Python dependencies, so we need to manually download them into the code package
pip install -r requirements.txt -t third_party

Ensure your project directory structure is as follows:

flask-cloudbase/
├── third_party/ # Third-party dependencies
├── app.py # Application main file
├── requirements.txt # Dependencies list
└── scf_bootstrap # Startup script

Step 7: Deploy to CloudBase HTTP cloud function

Deploy via the console

  1. Log in to the CloudBase console
  2. Select your environment and go to the cloud function page
  3. Click "New Cloud Function"
  4. Select "HTTP cloud function"
  5. Fill in the function name (such as: flask-app)
  6. Select runtime: Python 3.10
  7. Select submit method: Local folder upload
  8. Select the project root directory to upload the function code
  9. Automatic dependency installation: Enable this option
  10. Click the "Create" button and wait for deployment to complete

Deploy via CLI

For details, see Deploy HTTP cloud function

If you need to package manually:

# Create deployment package (excluding virtual environment)
zip -r fastapi-app.zip third_party app.py scf_bootstrap

Step 8: Access Your Application

After successful deployment, you can refer to Accessing Cloud Functions via HTTP to set up custom domain access to the

You can test the following endpoints:

  • Root path: / - Welcome message
  • Health Check: /health - Application Status
  • User List: /api/users - Obtain the user list
  • User Details: /api/users/1 - Retrieve a specific user
  • Create User: POST /api/users - Create a new user

Frequently Asked Questions

Q: Why must port 9000 be used?

A: CloudBase HTTP cloud functions require the application to listen on port 9000, which is the standard configuration of the platform.

Q: How to handle static files?

A: Flask can handle static files through the static folder or utilize CDN services.

Q: How to view application logs?

A: On the Cloud Functions page of the CloudBase console, click the function name to go to the details page and view the runtime logs.

Q: Which Python versions are supported?

A: CloudBase supports Python versions 3.6, 3.7, 3.9, and 3.10, with Python 3.10 recommended.

Q: How to handle CORS cross-origin issues?

A: You can use the flask-cors extension or manually set response headers to handle cross-origin requests.

Best Practices

1. Environment Variable Management

import os
from flask import Flask

app = Flask(__name__)

# Use environment variables
app.config['DEBUG'] = os.environ.get('DEBUG', 'False').lower() == 'true'
app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY', 'fallback-secret-key')
app.config['DATABASE_URL'] = os.environ.get('DATABASE_URL')

2. Add CORS support

pip install flask-cors
from flask_cors import CORS

app = Flask(__name__)
CORS(app, origins=['https://yourdomain.com'])

3. Log Configuration

import logging
from flask import Flask

app = Flask(__name__)

# Configure logging
if not app.debug:
logging.basicConfig(level=logging.INFO)
app.logger.info('Flask app startup')

4. Blueprint Code Organization

from flask import Blueprint

# Create Blueprint
api_bp = Blueprint('api', __name__, url_prefix='/api')

@api_bp.route('/users')
def get_users():
return jsonify({'users': []})

# Register Blueprint
app.register_blueprint(api_bp)

5. Database Integration

pip install flask-sqlalchemy
from flask_sqlalchemy import SQLAlchemy

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db'
db = SQLAlchemy(app)

class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(80), nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)

Advanced Features

1. Form Handling

pip install flask-wtf

2. Authentication

pip install flask-login flask-jwt-extended

3. API Documentation

pip install flask-restx

4. Caching Support

pip install flask-caching

Next steps