Introduction to Flask API Integration

Welcome to the fifth lesson of our course on building an image generation service with Flask! In our previous lessons, we've built several key components of our application: the PromptManager for formatting user inputs, the ImageManager for storing and processing images, the ImageGeneratorService for connecting to Google's Gemini API, and most recently, the ImageGeneratorController, which handles input validation and response formatting.

Now it's time to bring everything together by creating the Flask application that will expose our functionality through HTTP endpoints. This is the final piece of our backend architecture that will allow users to interact with our image generation service through a web interface.

In the previous lesson, we built the ImageGeneratorController, which acts as an intermediary between our service layer and the API routes we'll create today. The controller handles the business logic of validating inputs, calling the appropriate service methods, and formatting responses. Now, we'll create the Flask routes that will receive HTTP requests from clients and pass them to our controller.

Our Flask API will have three main routes:

  1. A route to serve the main HTML page
  2. A route to handle image generation requests
  3. A route to retrieve all previously generated images

By the end of this lesson, you'll have a complete Flask API that integrates with the controller we built previously, providing a clean interface for clients to generate and retrieve images.

Setting Up the Flask Application

Let's start by creating our Flask application. We'll set up the basic structure in our app/main.py file:

Python
1from flask import Flask, request, render_template 2from controllers.image_generator_controller import ImageGeneratorController 3 4app = Flask(__name__) 5app.secret_key = 'your_secret_key_here' 6 7image_generator_controller = ImageGeneratorController()

In this code, we're importing the necessary components from Flask: the Flask class to create our application, the request object to access incoming request data, and the render_template function to serve HTML templates. We're also importing our ImageGeneratorController class that we created in the previous lesson.

We create a Flask application instance by calling Flask(__name__). The __name__ parameter tells Flask where to look for resources like templates and static files. When we use __name__, Flask will look in the same directory as our script.

Next, we set a secret key for our application. The secret key is used by Flask and extensions to keep data safe. It's particularly important for features like sessions and cookies. In a production environment, you would want to use a strong, randomly generated key and keep it secure. For our development purposes, we're using a simple string, but remember to use a more secure key in a real application.

Finally, we create an instance of our ImageGeneratorController. This controller will handle the business logic for our API endpoints. By creating it once at the application level, we ensure that all routes can access the same controller instance, which helps maintain consistency across requests.

With these basic components in place, our Flask application is ready to have routes defined. The application will serve as the entry point for all client requests, routing them to the appropriate controller methods based on the URL and HTTP method.

Defining API Routes

Now that we have our Flask application set up, let's define the routes that will handle client requests.

Index Route

We'll start with the index route, which will serve the main HTML page of our application:

Python
1@app.route('/') 2def index(): 3 return render_template('image_generator.html')

The @app.route('/') decorator tells Flask that this function should be called when a client requests the root URL of our application. The function simply returns the result of render_template('image_generator.html'), which tells Flask to find the image_generator.html template in the templates directory and render it as the response.

Generate Image Route

Next, let's define the route for generating images:

Python
1@app.route('/api/generate_image', methods=['POST']) 2def generate_image(): 3 user_input = request.json.get('user_input') 4 return image_generator_controller.generate_image(user_input)

This route is more complex than the index route. The decorator @app.route('/api/generate_image', methods=['POST']) specifies that this function should be called when a client sends a POST request to the /api/generate_image URL. The methods=['POST'] parameter is important because it restricts this route to only accept POST requests, which is appropriate for an endpoint that creates a new resource (in this case, an image).

Inside the function, we extract the user_input from the JSON body of the request using request.json.get('user_input'). This assumes that the client is sending a JSON object with a user_input field. We then pass this input to our controller's generate_image method, which will validate the input, call the service to generate an image, and format the response.

The return value from the controller is passed directly back to the client. Remember from our previous lesson that the controller returns either a success response with the base64-encoded image data or an error response with an appropriate status code.

Get Images Route

Finally, let's define the route for retrieving all previously generated images:

Python
1@app.route('/api/get_images', methods=['GET']) 2def get_images(): 3 return image_generator_controller.get_images()

This route is defined with the decorator @app.route('/api/get_images', methods=['GET']), which specifies that it should be called when a client sends a GET request to the /api/get_images URL. GET is the appropriate HTTP method for retrieving resources.

The function simply calls our controller's get_images method, which retrieves all stored images and formats them as a JSON response. This response is then passed back to the client.

With these three routes, our Flask API provides a complete interface for clients to interact with our image generation service. Clients can view the main page, generate new images, and retrieve previously generated ones.

Configuring the Flask Server

Now that we have our Flask application and routes defined, let's configure the server to run our application. We'll add the following code at the end of our app/main.py file:

Python
1if __name__ == '__main__': 2 app.run(port=3000, host='0.0.0.0', debug=True)

This code block checks if the script is being run directly (as opposed to being imported as a module). If it is, it starts the Flask development server with specific configuration options.

The port=3000 parameter tells Flask to listen on port 3000 for incoming requests. You can choose any available port on your system, but 3000 is a common choice for development servers.

The host='0.0.0.0' parameter tells Flask to listen on all available network interfaces. This is important if you want to access your application from other devices on your network. If you only need to access it from the same machine, you could use host='127.0.0.1' or omit the parameter entirely (as 127.0.0.1 is the default).

The debug=True parameter enables Flask's debug mode, which provides helpful error messages and automatically reloads the server when you make changes to your code. This is very useful during development but should be disabled in a production environment for security and performance reasons.

When you run this script, you should see output similar to:

1 * Serving Flask app "main" (lazy loading) 2 * Environment: production 3 WARNING: This is a development server. Do not use it in a production deployment. 4 Use a production WSGI server instead. 5 * Debug mode: on 6 * Running on http://0.0.0.0:3000/ (Press CTRL+C to quit) 7 * Restarting with stat 8 * Debugger is active! 9 * Debugger PIN: 123-456-789

This indicates that your Flask server is running and ready to accept requests. You can access your application by opening a web browser and navigating to http://localhost:3000/ (or the appropriate IP address if accessing from another device).

On CodeSignal, the Flask application might already be running in the background, so you don't need to start it manually. However, understanding how to configure and run a Flask server is important for when you deploy your application in other environments.

Summary and Practice Preview

In this lesson, we've built a complete Flask API that integrates with our ImageGeneratorController to provide a web interface for our image generation service. Let's review what we've accomplished:

  1. We set up a Flask application with the necessary configuration, including a secret key for security.
  2. We created an index route to serve the main HTML page of our application.
  3. We implemented a POST endpoint for generating images, which extracts user input from the request and passes it to our controller.
  4. We set up a GET endpoint for retrieving all previously generated images.
  5. We configured the Flask server to run on a specific port and listen on all network interfaces, with debug mode enabled for development.

Our Flask API now provides a complete interface for clients to interact with our image generation service. The API routes receive HTTP requests, extract the necessary data, and pass it to our controller, which handles the business logic of validating inputs, calling the appropriate service methods, and formatting responses.

This completes the server-side portion of our image generation application. We've built a robust, modular architecture with a clear separation of concerns:

  • The PromptManager handles prompt formatting
  • The ImageManager manages image storage and processing
  • The ImageGeneratorService connects to the Gemini API and coordinates the other components
  • The ImageGeneratorController validates inputs and formats responses
  • The Flask API routes client requests to the appropriate controller methods

In the upcoming practice exercises, you'll have the opportunity to test the API endpoints we've created. You'll send requests to generate images with different prompts and retrieve the stored images. You'll also explore how the API handles error cases, such as missing or invalid inputs.

By the end of these exercises, you'll have a solid understanding of how to build a complete web API with Flask, integrating it with a controller-based architecture to provide a clean, consistent interface for clients. This knowledge will be valuable not just for image generation services but for any web application you build in the future.

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal