杰瑞科技汇

如何用Python实现RESTful API?

Of course! Building a RESTful API with Python is a very common task. The most popular and beginner-friendly library for this is Flask.

如何用Python实现RESTful API?-图1
(图片来源网络,侵删)

I'll guide you through the process step-by-step, starting with a simple "Hello World" API and building up to a more complete example with database interaction, best practices, and deployment.

What is a RESTful API?

First, a quick definition. REST (Representational State Transfer) is an architectural style for designing networked applications. A RESTful API uses standard HTTP methods to perform operations on resources.

  • Resources: These are the "nouns" of your API (e.g., /users, /products, /orders).
  • HTTP Methods (Verbs): These are the actions you perform on the resources.
    • GET: Retrieve a resource or a list of resources. (Read)
    • POST: Create a new resource. (Create)
    • PUT or PATCH: Update an existing resource. (Update)
    • DELETE: Remove a resource. (Delete)

Part 1: The Basics with Flask

Flask is a lightweight and flexible web framework perfect for building APIs.

Step 1: Installation

First, you need to install Flask. It's best practice to do this in a virtual environment.

如何用Python实现RESTful API?-图2
(图片来源网络,侵删)
# Create a virtual environment
python -m venv venv
# Activate it
# On macOS/Linux:
source venv/bin/activate
# On Windows:
.\venv\Scripts\activate
# Install Flask
pip install Flask

Step 2: A Simple "Hello World" API

Create a file named app.py and add the following code:

# app.py
from flask import Flask, jsonify
# Create an instance of the Flask class
app = Flask(__name__)
# Define a route and a function to handle requests to that route
@app.route('/')
def hello_world():
    return 'Hello, World!'
# To run the app:
# if __name__ == '__main__':
#     app.run(debug=True)

This simple app defines a single route . When you navigate to that URL, it returns the string "Hello, World!".

To run this, add the last block of code to app.py and execute it:

python app.py

You'll see output indicating the server is running, usually on http://127.0.0.1:5000. Open that URL in your browser.

如何用Python实现RESTful API?-图3
(图片来源网络,侵删)

Step 3: Your First RESTful Endpoint

Let's create an endpoint that returns data in JSON format, which is the standard for APIs.

Modify app.py:

# app.py
from flask import Flask, jsonify
app = Flask(__name__)
# A simple in-memory "database"
books = [
    {'id': 1, 'title': 'The Lord of the Rings', 'author': 'J.R.R. Tolkien'},
    {'id': 2, 'title': 'The Hobbit', 'author': 'J.R.R. Tolkien'},
    {'id': 3, 'title': '1984', 'author': 'George Orwell'}
]
# Route to get all books (GET)
@app.route('/books', methods=['GET'])
def get_books():
    return jsonify(books)
# Route to get a single book by its ID (GET)
@app.route('/books/<int:book_id>', methods=['GET'])
def get_book(book_id):
    book = next((book for book in books if book['id'] == book_id), None)
    if book is None:
        # Return a 404 Not Found error if the book doesn't exist
        return jsonify({'error': 'Book not found'}), 404
    return jsonify(book)
if __name__ == '__main__':
    app.run(debug=True)

Key changes:

  • jsonify: Converts Python dictionaries into JSON responses.
  • methods=['GET']: Explicitly states that this endpoint only responds to GET requests.
  • <int:book_id>: This is a dynamic part of the URL. Flask will capture the value and pass it as an integer argument to your function.
  • next(): A concise way to find the first item in a list that matches a condition.
  • Status Codes: We return a 404 Not Found status code with an error message if the book doesn't exist. This is a crucial part of good API design.

Part 2: A More Complete CRUD API

Let's build a full API for managing "tasks" (Create, Read, Update, Delete) and add a POST endpoint.

Step 1: Project Structure

For a real project, it's good to organize your code.

/my-api
|-- /venv
|-- app.py
|-- /models
|   |-- task.py
|-- /routes
|   |-- task_routes.py
|-- main.py

Step 2: The Models

The models folder will contain the data structure for our resources.

models/task.py

# models/task.py
class Task:
    def __init__(self, id, title, description, done=False):
        self.id = id
        self.title = title
        self.description = description
        self.done = done
    def to_dict(self):
        return {
            'id': self.id,
            'title': self.title,
            'description': self.description,
            'done': self.done
        }

Step 3: The Routes

The routes folder will contain the logic for each API endpoint.

routes/task_routes.py

# routes/task_routes.py
from flask import Blueprint, request, jsonify
from models.task import Task
# Create a Blueprint for task-related routes
task_bp = Blueprint('tasks', __name__)
# In-memory "database" for tasks
tasks = [
    Task(1, 'Learn Python', 'Study Flask framework', False),
    Task(2, 'Build an API', 'Create a RESTful API with Python', True)
]
next_task_id = 3
# --- CRUD Operations ---
# GET all tasks
@task_bp.route('/tasks', methods=['GET'])
def get_all_tasks():
    return jsonify([task.to_dict() for task in tasks])
# GET a single task by ID
@task_bp.route('/tasks/<int:task_id>', methods=['GET'])
def get_task(task_id):
    task = next((t for t in tasks if t.id == task_id), None)
    if task is None:
        return jsonify({'error': 'Task not found'}), 404
    return jsonify(task.to_dict())
# CREATE a new task (POST)
@task_bp.route('/tasks', methods=['POST'])
def create_task():
    global next_task_id
    if not request.json or 'title' not in request.json:
        return jsonify({'error': 'Missing title in request body'}), 400
    new_task = Task(
        id=next_task_id,
        title=request.json['title'],
        description=request.json.get('description', ""),
        done=False
    )
    tasks.append(new_task)
    next_task_id += 1
    # Return the newly created task with a 201 Created status
    return jsonify(new_task.to_dict()), 201
# UPDATE a task (PUT)
@task_bp.route('/tasks/<int:task_id>', methods=['PUT'])
def update_task(task_id):
    task = next((t for t in tasks if t.id == task_id), None)
    if task is None:
        return jsonify({'error': 'Task not found'}), 404
    if not request.json:
        return jsonify({'error': 'Request body must be JSON'}), 400
    task.title = request.json.get('title', task.title)
    task.description = request.json.get('description', task.description)
    task.done = request.json.get('done', task.done)
    return jsonify(task.to_dict())
# DELETE a task
@task_bp.route('/tasks/<int:task_id>', methods=['DELETE'])
def delete_task(task_id):
    global tasks
    task_to_delete = next((t for t in tasks if t.id == task_id), None)
    if task_to_delete is None:
        return jsonify({'error': 'Task not found'}), 404
    tasks = [t for t in tasks if t.id != task_id]
    return jsonify({'result': True, 'message': 'Task deleted successfully'})

Step 4: The Main Application File

Now, we tie everything together in main.py.

main.py

# main.py
from flask import Flask
from routes.task_routes import task_bp
app = Flask(__name__)
# Register the Blueprint
app.register_blueprint(task_bp, url_prefix='/api/v1')
if __name__ == '__main__':
    app.run(debug=True)

Explanation:

  • Blueprint: A Flask Blueprint allows you to organize your application into components. It's like a mini-application that can be registered with the main app.
  • url_prefix='/api/v1': This adds /api/v1 to the beginning of all routes defined in task_bp. So, the full path to get all tasks will be /api/v1/tasks. This is great for versioning your API.

Part 3: Best Practices & Next Steps

Using a Real Database (SQLAlchemy)

In-memory data is lost every time the server restarts. Let's use Flask-SQLAlchemy to connect to a real database (like SQLite for development).

Installation: pip install Flask-SQLAlchemy

Example Integration:

In main.py, you'd initialize the database extension:

# main.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from routes.task_routes import task_bp
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///tasks.db' # Use a file-based database
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
# ... (rest of the code)

Then, you would refactor your Task model to inherit from db.Model and define the columns. The routes would then use db.session to query, add, and commit changes to the database instead of manipulating a list.

API Documentation with Swagger/OpenAPI

Manually documenting an API is tedious. Use Flask-Swagger-UI or Flask-RESTx to generate interactive documentation.

With Flask-RESTx, you can define your API with decorators, and it automatically creates a beautiful Swagger UI.

Data Validation

Ensure the data sent by the client is valid. Marshmallow is a popular library for object serialization/deserialization and validation in Python. It works perfectly with Flask to validate request data before it reaches your logic.

Security

  • Authentication: Use libraries like Flask-JWT-Extended or Flask-Login to protect your endpoints so only authorized users can access them.
  • Input Sanitization: Always validate and sanitize user input to prevent security vulnerabilities like SQL Injection or Cross-Site Scripting (XSS).

Testing

Write automated tests for your API using a library like pytest. You can create a test client that simulates requests to your API and checks if the responses are correct.

Deployment

When you're ready to go live, you'll need a production-grade WSGI server like Gunicorn or Waitress to run your Flask application, and a reverse proxy like Nginx to handle incoming traffic and serve static files.

Example with Gunicorn: pip install gunicorn gunicorn -w 4 -b 0.0.0.0:8000 main:app

This command runs 4 worker processes (-w 4) and binds the server to all available network interfaces on port 8000 (-b 0.0.0.0:8000).


Alternative Frameworks

While Flask is excellent, other frameworks are also very popular for building APIs in Python:

  • Django REST framework (DRF): Built on top of the Django framework. It's incredibly powerful, feature-rich (authentication, permissions, throttling), and comes with a browsable API. It's a great choice if you're already using Django or need a lot of boilerplate handled for you.
  • FastAPI: A modern, high-performance framework. It's known for its incredible speed (thanks to Starlette and Pydantic), automatic data validation and documentation (using OpenAPI/Swagger), and ease of use. It's becoming a very popular choice for new projects.

For a beginner, Flask is the perfect starting point due to its simplicity and gentle learning curve. As you become more comfortable, you can explore FastAPI for its performance or DRF if you need the Django ecosystem.

分享:
扫描分享到社交APP
上一篇
下一篇