Building a GraphQL API for a Social Media App with FastAPI

Expedience Apps

Mobile Engineer
Software Architect
Flutter Developer
GraphQL
Python
In recent years, GraphQL has become a popular choice for APIs due to its flexibility and efficiency in data fetching. In this blog, we'll explore how to build a GraphQL API for a social media application. We'll cover the basics of setting up a GraphQL server, defining a schema, and creating resolvers.

Why GraphQL for a Social Media App?

GraphQL offers several advantages over traditional REST APIs, making it an ideal choice for a social media application:
Flexible Data Retrieval: Clients can request exactly the data they need, avoiding over-fetching and under-fetching issues.
Efficient Querying: Multiple related resources can be fetched in a single request.
Strongly Typed Schema: The schema serves as a contract between the client and server, ensuring data consistency and reducing errors.

Setting Up the Backend with FastAPI and Strawberry

First, we'll set up the backend using FastAPI and Strawberry. FastAPI is a modern, fast (high-performance) web framework for building APIs with Python, and Strawberry is a library for building GraphQL APIs.

Step 1: Install Dependencies

First, create a new virtual environment and install the necessary dependencies:



Step 2: Define the GraphQL Schema

Create a new file, main.py, and define the GraphQL schema using Strawberry:
import strawberry
from typing import List, Optional
from fastapi import FastAPI
from strawberry.fastapi import GraphQLRouter

@strawberry.type
class User:
id: strawberry.ID
username: str
email: str
posts: List['Post']

@strawberry.type
class Post:
id: strawberry.ID
content: str
author: User

@strawberry.type
class Query:
users: List[User]
posts: List[Post]

@strawberry.type
class Mutation:
@strawberry.mutation
def create_user(self, username: str, email: str) -> User:
new_user = User(id=str(len(users) + 1), username=username, email=email, posts=[])
users.append(new_user)
return new_user

@strawberry.mutation
def create_post(self, content: str, author_id: strawberry.ID) -> Post:
author = next(user for user in users if user.id == author_id)
new_post = Post(id=str(len(posts) + 1), content=content, author=author)
posts.append(new_post)
author.posts.append(new_post)
return new_post

schema = strawberry.Schema(query=Query, mutation=Mutation)

app = FastAPI()
graphql_app = GraphQLRouter(schema)

app.include_router(graphql_app, prefix="/graphql")

# Sample data
users = [
User(id="1", username="alice", email="alice@example.com", posts=[]),
User(id="2", username="bob", email="bob@example.com", posts=[]),
]

posts = []

Step 3: Run the Server

Run the FastAPI server using Uvicorn:

Open your browser and navigate to http://localhost:8000/graphql. You should see the GraphQL playground interface where you can run GraphQL queries and mutations.

Setting Up the Frontend with Flutter

Now, let's set up the frontend using Flutter. We'll use the graphql_flutter package to interact with our GraphQL API.

Step 1: Install Dependencies

Add the graphql_flutter package to your pubspec.yaml file:
dependencies:
flutter:
sdk: flutter
graphql_flutter: ^5.0.1
Run 'flutter pub get' to install the dependencies.

Step 2: Set Up the GraphQL Client

Create a new file, graphql_config.dart, and set up the GraphQL client:
import 'package:flutter/material.dart';
import 'package:graphql_flutter/graphql_flutter.dart';

class GraphQLConfig {
static final HttpLink httpLink = HttpLink(
'http://localhost:8000/graphql',
);

static ValueNotifier<GraphQLClient> client = ValueNotifier(
GraphQLClient(
link: httpLink,
cache: GraphQLCache(store: InMemoryStore()),
),
);

static GraphQLClient clientToQuery() {
return GraphQLClient(
link: httpLink,
cache: GraphQLCache(store: InMemoryStore()),
);
}
}

Step 3: Creating the Flutter UI

Next, create a basic Flutter UI to interact with the GraphQL API. Create a new file, main.dart, and add the following code:
import 'package:flutter/material.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
import 'graphql_config.dart';

void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GraphQLProvider(
client: GraphQLConfig.client,
child: CacheProvider(
child: MaterialApp(
title: 'Flutter GraphQL Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
),
),
);
}
}

class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
final String readUsers = """
query {
users {
id
username
email
}
}
""";

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('GraphQL Users'),
),
body: Query(
options: QueryOptions(document: gql(readUsers)),
builder: (QueryResult result, {VoidCallback refetch, FetchMore fetchMore}) {
if (result.hasException) {
return Text(result.exception.toString());
}

if (result.isLoading) {
return Center(child: CircularProgressIndicator());
}

List users = result.data['users'];

return ListView.builder(
itemCount: users.length,
itemBuilder: (context, index) {
final user = users[index];
return ListTile(
title: Text(user['username']),
subtitle: Text(user['email']),
);
},
);
},
),
);
}
}

Conclusion

In this blog, we have set up a basic GraphQL API using FastAPI and Strawberry for a social media application. We also created a Flutter frontend to interact with the API. This setup provides a strong foundation for building more complex features, such as user authentication, real-time updates, and more advanced querying capabilities. With the flexibility and efficiency of GraphQL combined with the performance of FastAPI, social media applications can scale and adapt to various client requirements seamlessly.
Partner With Expedience
View Services