How to Connect Python to Firebase Database: Complete Guide
Firebase is Google's comprehensive app development platform that provides cloud-hosted NoSQL databases, real-time synchronization, and backend services. When combined with Python, Firebase enables developers to build serverless, real-time applications with minimal infrastructure management. This comprehensive guide covers everything you need to know about connecting Python to Firebase.
Why Use Firebase with Python?
Firebase with Python offers powerful capabilities:
- Real-time database with automatic synchronization
- Cloud Firestore for flexible, scalable NoSQL storage
- Serverless architecture with no infrastructure management
- Built-in authentication and security rules
- Automatic scaling based on demand
- Offline support and data persistence
- Real-time listeners for live updates
- Perfect for mobile and web app backends
Prerequisites
Before connecting Python to Firebase, ensure you have:
- Python 3.6 or higher installed
- Firebase project created in Firebase Console
- Service account credentials (JSON file)
- Basic understanding of NoSQL databases
- Firebase Admin SDK installed
Installing Firebase Admin SDK
Install the official Firebase Admin SDK for Python:
bash
pip install firebase-admin
Setting Up Firebase Project
- Go to Firebase Console (console.firebase.google.com)
- Create a new project or select existing
- Navigate to Project Settings > Service Accounts
- Generate new private key (downloads JSON file)
- Save the JSON file securely
Basic Connection to Firebase
python
import firebase_admin
from firebase_admin import credentials, firestore
# Initialize Firebase with service account
cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
# Get Firestore client
db = firestore.client()
print("Connected to Firebase successfully!")
Connection with Error Handling
python
import firebase_admin
from firebase_admin import credentials, firestore
from firebase_admin.exceptions import FirebaseError
def initialize_firebase():
try:
# Check if already initialized
if not firebase_admin._apps:
cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
db = firestore.client()
print("Successfully connected to Firebase")
return db
except FileNotFoundError:
print("Service account key file not found")
return None
except FirebaseError as e:
print(f"Firebase error: {e}")
return None
except Exception as e:
print(f"Error: {e}")
return None
# Usage
db = initialize_firebase()
Using Environment Variables
python
import firebase_admin
from firebase_admin import credentials
import os
# Set environment variable
# export GOOGLE_APPLICATION_CREDENTIALS="/path/to/serviceAccountKey.json"
# Initialize with default credentials
cred = credentials.ApplicationDefault()
firebase_admin.initialize_app(cred)
print("Initialized with application default credentials")
Working with Firestore
Creating Documents
python
import firebase_admin
from firebase_admin import credentials, firestore
from datetime import datetime
# Initialize Firebase
cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
db = firestore.client()
# Add document with auto-generated ID
employee_ref = db.collection('employees').document()
employee_ref.set({
'first_name': 'John',
'last_name': 'Doe',
'email': 'john.doe@company.com',
'department': 'Engineering',
'salary': 75000,
'hire_date': datetime.now(),
'skills': ['Python', 'Firebase', 'Cloud'],
'active': True
})
print(f"Employee created with ID: {employee_ref.id}")
# Add document with custom ID
db.collection('employees').document('EMP001').set({
'first_name': 'Jane',
'last_name': 'Smith',
'email': 'jane@company.com',
'department': 'Marketing',
'salary': 68000
})
print("Employee created with custom ID: EMP001")
Adding Multiple Documents
python
import firebase_admin
from firebase_admin import credentials, firestore
cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
db = firestore.client()
# Add multiple documents
employees = [
{'first_name': 'Bob', 'last_name': 'Johnson', 'department': 'Sales', 'salary': 72000},
{'first_name': 'Alice', 'last_name': 'Williams', 'department': 'Engineering', 'salary': 80000},
{'first_name': 'Charlie', 'last_name': 'Brown', 'department': 'HR', 'salary': 62000}
]
for emp in employees:
db.collection('employees').add(emp)
print(f"Added employee: {emp['first_name']} {emp['last_name']}")
print(f"Added {len(employees)} employees")
Reading Documents
Get Single Document
python
import firebase_admin
from firebase_admin import credentials, firestore
cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
db = firestore.client()
# Get document by ID
doc_ref = db.collection('employees').document('EMP001')
doc = doc_ref.get()
if doc.exists:
employee = doc.to_dict()
print(f"Employee: {employee['first_name']} {employee['last_name']}")
print(f"Department: {employee['department']}")
print(f"Salary: ${employee['salary']}")
else:
print("Document not found")
Get All Documents in Collection
python
import firebase_admin
from firebase_admin import credentials, firestore
cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
db = firestore.client()
# Get all employees
employees_ref = db.collection('employees')
docs = employees_ref.stream()
print("All Employees:")
for doc in docs:
employee = doc.to_dict()
print(f"ID: {doc.id}, Name: {employee['first_name']} {employee['last_name']}")
Query with Filters
python
import firebase_admin
from firebase_admin import credentials, firestore
cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
db = firestore.client()
# Query employees in Engineering department
engineers_ref = db.collection('employees').where('department', '==', 'Engineering')
docs = engineers_ref.stream()
print("Engineering Employees:")
for doc in docs:
employee = doc.to_dict()
print(f"{employee['first_name']} {employee['last_name']} - ${employee['salary']}")
# Multiple filters
high_earners = db.collection('employees')\
.where('department', '==', 'Engineering')\
.where('salary', '>', 70000)\
.stream()
print("\nHigh-earning Engineers:")
for doc in high_earners:
employee = doc.to_dict()
print(f"{employee['first_name']} {employee['last_name']} - ${employee['salary']}")
Query with Ordering and Limiting
python
import firebase_admin
from firebase_admin import credentials, firestore
cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
db = firestore.client()
# Get top 5 highest paid employees
top_earners = db.collection('employees')\
.order_by('salary', direction=firestore.Query.DESCENDING)\
.limit(5)\
.stream()
print("Top 5 Earners:")
for idx, doc in enumerate(top_earners, 1):
employee = doc.to_dict()
print(f"{idx}. {employee['first_name']} {employee['last_name']} - ${employee['salary']}")
Updating Documents
Update Specific Fields
python
import firebase_admin
from firebase_admin import credentials, firestore
cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
db = firestore.client()
# Update specific fields
doc_ref = db.collection('employees').document('EMP001')
doc_ref.update({
'salary': 85000,
'department': 'Senior Engineering'
})
print("Employee updated successfully")
# Update using field path
doc_ref.update({
'skills': firestore.ArrayUnion(['Docker', 'Kubernetes'])
})
print("Skills added to employee")
Increment Numeric Fields
python
import firebase_admin
from firebase_admin import credentials, firestore
cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
db = firestore.client()
# Increment salary
doc_ref = db.collection('employees').document('EMP001')
doc_ref.update({
'salary': firestore.Increment(5000)
})
print("Salary incremented by $5000")
Update or Create (Upsert)
python
import firebase_admin
from firebase_admin import credentials, firestore
cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
db = firestore.client()
# Set with merge (updates if exists, creates if doesn't)
doc_ref = db.collection('employees').document('EMP002')
doc_ref.set({
'first_name': 'Sarah',
'last_name': 'Connor',
'department': 'Security'
}, merge=True)
print("Document upserted successfully")
Deleting Documents
python
import firebase_admin
from firebase_admin import credentials, firestore
cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
db = firestore.client()
# Delete a document
doc_ref = db.collection('employees').document('EMP999')
doc_ref.delete()
print("Employee deleted")
# Delete a field from document
doc_ref = db.collection('employees').document('EMP001')
doc_ref.update({
'temp_field': firestore.DELETE_FIELD
})
print("Field deleted from document")
Batch Operations
python
import firebase_admin
from firebase_admin import credentials, firestore
cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
db = firestore.client()
# Create batch
batch = db.batch()
# Add multiple operations to batch
emp1_ref = db.collection('employees').document('EMP001')
batch.update(emp1_ref, {'salary': 90000})
emp2_ref = db.collection('employees').document('EMP002')
batch.set(emp2_ref, {'first_name': 'New', 'last_name': 'Employee', 'department': 'IT'})
emp3_ref = db.collection('employees').document('EMP003')
batch.delete(emp3_ref)
# Commit batch
batch.commit()
print("Batch operations completed")
Transactions
python
import firebase_admin
from firebase_admin import credentials, firestore
cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
db = firestore.client()
# Transaction for atomic operations
@firestore.transactional
def transfer_budget(transaction, from_dept_ref, to_dept_ref, amount):
# Read documents
from_dept = from_dept_ref.get(transaction=transaction).to_dict()
to_dept = to_dept_ref.get(transaction=transaction).to_dict()
# Check if sufficient budget
if from_dept['budget'] < amount:
raise ValueError("Insufficient budget")
# Perform transfer
transaction.update(from_dept_ref, {'budget': from_dept['budget'] - amount})
transaction.update(to_dept_ref, {'budget': to_dept['budget'] + amount})
# Execute transaction
from_ref = db.collection('departments').document('Engineering')
to_ref = db.collection('departments').document('Marketing')
transaction = db.transaction()
try:
transfer_budget(transaction, from_ref, to_ref, 10000)
print("Budget transfer completed successfully")
except ValueError as e:
print(f"Transaction failed: {e}")
Real-time Listeners
python
import firebase_admin
from firebase_admin import credentials, firestore
import time
cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
db = firestore.client()
# Create a callback function
def on_snapshot(doc_snapshot, changes, read_time):
for doc in doc_snapshot:
print(f"Received document snapshot: {doc.id}")
employee = doc.to_dict()
print(f"Name: {employee['first_name']} {employee['last_name']}")
for change in changes:
if change.type.name == 'ADDED':
print(f"New employee: {change.document.id}")
elif change.type.name == 'MODIFIED':
print(f"Modified employee: {change.document.id}")
elif change.type.name == 'REMOVED':
print(f"Removed employee: {change.document.id}")
# Watch a collection
employees_ref = db.collection('employees')
doc_watch = employees_ref.on_snapshot(on_snapshot)
print("Listening for changes... Press Ctrl+C to stop")
# Keep the script running
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
print("\nStopping listener")
doc_watch.unsubscribe()
Working with Subcollections
python
import firebase_admin
from firebase_admin import credentials, firestore
cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
db = firestore.client()
# Create document with subcollection
employee_ref = db.collection('employees').document('EMP001')
# Add performance reviews as subcollection
reviews_ref = employee_ref.collection('reviews')
reviews_ref.add({
'year': 2024,
'rating': 'Excellent',
'comments': 'Outstanding performance',
'reviewer': 'Manager Name'
})
print("Review added to subcollection")
# Query subcollection
reviews = employee_ref.collection('reviews')\
.where('year', '==', 2024)\
.stream()
print("\n2024 Reviews:")
for review in reviews:
data = review.to_dict()
print(f"Rating: {data['rating']}, Comments: {data['comments']}")
Working with Array Fields
python
import firebase_admin
from firebase_admin import credentials, firestore
cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
db = firestore.client()
doc_ref = db.collection('employees').document('EMP001')
# Add elements to array
doc_ref.update({
'skills': firestore.ArrayUnion(['GraphQL', 'TypeScript'])
})
print("Skills added to array")
# Remove elements from array
doc_ref.update({
'skills': firestore.ArrayRemove(['GraphQL'])
})
print("Skill removed from array")
# Query documents containing array element
docs = db.collection('employees')\
.where('skills', 'array_contains', 'Python')\
.stream()
print("\nEmployees with Python skill:")
for doc in docs:
employee = doc.to_dict()
print(f"{employee['first_name']} {employee['last_name']}")
Using Firebase Realtime Database
python
import firebase_admin
from firebase_admin import credentials, db
# Initialize with Realtime Database URL
cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred, {
'databaseURL': 'https://your-project.firebaseio.com'
})
# Get reference to database
ref = db.reference('/')
# Write data
employees_ref = ref.child('employees')
employees_ref.set({
'EMP001': {
'first_name': 'John',
'last_name': 'Doe',
'department': 'Engineering',
'salary': 75000
},
'EMP002': {
'first_name': 'Jane',
'last_name': 'Smith',
'department': 'Marketing',
'salary': 68000
}
})
print("Data written to Realtime Database")
# Read data
employee = employees_ref.child('EMP001').get()
print(f"\nEmployee: {employee['first_name']} {employee['last_name']}")
# Update data
employees_ref.child('EMP001').update({
'salary': 80000
})
print("Employee salary updated")
# Delete data
employees_ref.child('EMP002').delete()
print("Employee deleted")
Working with Cloud Storage
python
import firebase_admin
from firebase_admin import credentials, storage
cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred, {
'storageBucket': 'your-project.appspot.com'
})
# Get bucket
bucket = storage.bucket()
# Upload file
blob = bucket.blob('employee_photos/emp001.jpg')
blob.upload_from_filename('/path/to/local/photo.jpg')
print("File uploaded successfully")
# Make file publicly accessible
blob.make_public()
print(f"Public URL: {blob.public_url}")
# Download file
blob = bucket.blob('employee_photos/emp001.jpg')
blob.download_to_filename('/path/to/download/photo.jpg')
print("File downloaded successfully")
# Delete file
blob = bucket.blob('employee_photos/emp001.jpg')
blob.delete()
print("File deleted")
Authentication
python
import firebase_admin
from firebase_admin import credentials, auth
cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
# Create user
user = auth.create_user(
email='user@example.com',
password='secretPassword',
display_name='John Doe'
)
print(f"User created: {user.uid}")
# Get user by email
user = auth.get_user_by_email('user@example.com')
print(f"User: {user.display_name}, Email: {user.email}")
# Update user
auth.update_user(
user.uid,
display_name='John Smith',
email_verified=True
)
print("User updated")
# Delete user
auth.delete_user(user.uid)
print("User deleted")
# Create custom token
custom_token = auth.create_custom_token(user.uid)
print(f"Custom token created: {custom_token.decode()}")
# Verify ID token
try:
decoded_token = auth.verify_id_token(id_token)
uid = decoded_token['uid']
print(f"Token verified for user: {uid}")
except Exception as e:
print(f"Token verification failed: {e}")
Complete Application Example
python
import firebase_admin
from firebase_admin import credentials, firestore
from datetime import datetime
class EmployeeManager:
def __init__(self, service_account_path):
if not firebase_admin._apps:
cred = credentials.Certificate(service_account_path)
firebase_admin.initialize_app(cred)
self.db = firestore.client()
self.collection = 'employees'
def create_employee(self, first_name, last_name, email, department, salary):
"""Create a new employee"""
doc_ref = self.db.collection(self.collection).document()
doc_ref.set({
'first_name': first_name,
'last_name': last_name,
'email': email,
'department': department,
'salary': salary,
'hire_date': datetime.now(),
'active': True
})
return doc_ref.id
def get_employee(self, employee_id):
"""Get employee by ID"""
doc = self.db.collection(self.collection).document(employee_id).get()
if doc.exists:
return {'id': doc.id, **doc.to_dict()}
return None
def get_all_employees(self):
"""Get all employees"""
docs = self.db.collection(self.collection).stream()
employees = []
for doc in docs:
employees.append({'id': doc.id, **doc.to_dict()})
return employees
def get_employees_by_department(self, department):
"""Get employees by department"""
docs = self.db.collection(self.collection)\
.where('department', '==', department)\
.stream()
employees = []
for doc in docs:
employees.append({'id': doc.id, **doc.to_dict()})
return employees
def update_salary(self, employee_id, new_salary):
"""Update employee salary"""
doc_ref = self.db.collection(self.collection).document(employee_id)
doc_ref.update({'salary': new_salary})
return True
def add_skill(self, employee_id, skill):
"""Add skill to employee"""
doc_ref = self.db.collection(self.collection).document(employee_id)
doc_ref.update({
'skills': firestore.ArrayUnion([skill])
})
return True
def delete_employee(self, employee_id):
"""Soft delete employee"""
doc_ref = self.db.collection(self.collection).document(employee_id)
doc_ref.update({'active': False})
return True
def search_employees(self, search_term):
"""Search employees by name"""
# Note: Firestore doesn't support full-text search natively
# This is a simple implementation
all_employees = self.get_all_employees()
results = []
for emp in all_employees:
full_name = f"{emp['first_name']} {emp['last_name']}".lower()
if search_term.lower() in full_name:
results.append(emp)
return results
def get_department_stats(self):
"""Get statistics by department"""
docs = self.db.collection(self.collection).stream()
stats = {}
for doc in docs:
employee = doc.to_dict()
dept = employee.get('department', 'Unknown')
if dept not in stats:
stats[dept] = {
'count': 0,
'total_salary': 0,
'salaries': []
}
stats[dept]['count'] += 1
stats[dept]['total_salary'] += employee.get('salary', 0)
stats[dept]['salaries'].append(employee.get('salary', 0))
# Calculate averages and ranges
for dept in stats:
salaries = stats[dept]['salaries']
stats[dept]['avg_salary'] = stats[dept]['total_salary'] / stats[dept]['count']
stats[dept]['min_salary'] = min(salaries)
stats[dept]['max_salary'] = max(salaries)
del stats[dept]['salaries']
del stats[dept]['total_salary']
return stats
def add_performance_review(self, employee_id, year, rating, comments):
"""Add performance review as subcollection"""
doc_ref = self.db.collection(self.collection).document(employee_id)
reviews_ref = doc_ref.collection('reviews')
reviews_ref.add({
'year': year,
'rating': rating,
'comments': comments,
'created_at': datetime.now()
})
return True
def get_employee_reviews(self, employee_id):
"""Get all reviews for an employee"""
doc_ref = self.db.collection(self.collection).document(employee_id)
reviews = doc_ref.collection('reviews').stream()
review_list = []
for review in reviews:
review_list.append({'id': review.id, **review.to_dict()})
return review_list
# Usage
manager = EmployeeManager('/path/to/serviceAccountKey.json')
# Create employee
emp_id = manager.create_employee(
'Sarah', 'Connor', 'sarah@company.com', 'Security', 78000
)
print(f"Created employee with ID: {emp_id}")
# Get employee
employee = manager.get_employee(emp_id)
print(f"Employee: {employee['first_name']} {employee['last_name']}")
# Get all employees
all_employees = manager.get_all_employees()
print(f"\nTotal employees: {len(all_employees)}")
# Get by department
engineers = manager.get_employees_by_department('Engineering')
print(f"Engineers: {len(engineers)}")
# Update salary
manager.update_salary(emp_id, 82000)
print("Salary updated")
# Add skill
manager.add_skill(emp_id, 'Cloud Security')
print("Skill added")
# Get department stats
stats = manager.get_department_stats()
print("\nDepartment Statistics:")
for dept, data in stats.items():
print(f"{dept}:")
print(f" Employees: {data['count']}")
print(f" Avg Salary: ${data['avg_salary']:.2f}")
print(f" Range: ${data['min_salary']} - ${data['max_salary']}")
# Add performance review
manager.add_performance_review(emp_id, 2024, 'Excellent', 'Outstanding performance')
print("\nPerformance review added")
# Get reviews
reviews = manager.get_employee_reviews(emp_id)
print(f"Total reviews: {len(reviews)}")
# Search employees
results = manager.search_employees('Sarah')
print(f"\nSearch results: {len(results)} found")
Pagination
python
import firebase_admin
from firebase_admin import credentials, firestore
cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
db = firestore.client()
# Initial query
page_size = 10
employees_ref = db.collection('employees').limit(page_size)
docs = employees_ref.stream()
employees_list = list(docs)
print(f"Page 1: {len(employees_list)} employees")
# Get next page
if employees_list:
last_doc = employees_list[-1]
next_query = db.collection('employees')\
.start_after(last_doc)\
.limit(page_size)
next_docs = next_query.stream()
next_page = list(next_docs)
print(f"Page 2: {len(next_page)} employees")
Security Rules Testing
python
import firebase_admin
from firebase_admin import credentials, firestore
cred = credentials.Certificate('/path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
db = firestore.client()
# Test security rules (requires appropriate permissions)
try:
# Attempt to access protected collection
docs = db.collection('protected_data').stream()
for doc in docs:
print(f"Document: {doc.id}")
except Exception as e:
print(f"Access denied: {e}")
Best Practices
Follow these best practices when using Firebase with Python:
- Secure service account keys - never commit to version control
- Use environment variables for credentials
- Implement proper error handling for all operations
- Use batch operations for multiple writes
- Leverage subcollections for hierarchical data
- Create indexes for complex queries
- Use transactions for atomic operations
- Monitor usage in Firebase Console
- Implement pagination for large datasets
- Use real-time listeners carefully to avoid costs
- Structure data to minimize reads
- Use security rules to protect data
- Cache frequently accessed data on client side
- Avoid deep nesting in documents
- Use appropriate data types for fields
Conclusion
Connecting Python to Firebase provides a powerful foundation for building serverless, real-time applications with minimal infrastructure management. Firebase's comprehensive suite of tools including Firestore, Realtime Database, Authentication, and Cloud Storage, combined with Python's versatility, enables rapid development of scalable applications. By following the examples and best practices in this guide, you'll be able to build robust applications that leverage Firebase's real-time capabilities, automatic scaling, and seamless integration with other Google Cloud services. Whether you're building mobile backends, web applications, or IoT platforms, mastering Python-Firebase connectivity is essential for modern serverless application development.