Django: How to implement proper logging for production applications?

Open
Aug 30, 2025 232 views 3 answers
49

I'm working on a Django project and encountering an issue with Django REST API. Here's my current implementation:


# models.py
# views.py
from django.shortcuts import render
from .models import Article

def article_list(request):
    articles = Article.objects.all()
    for article in articles:
        print(article.author.username)  # N+1 problem here
    return render(request, 'articles.html', {'articles': articles})

The specific error I'm getting is: "django.core.exceptions.ValidationError: Enter a valid email address"

I've already tried the following approaches:

  • Checked Django documentation and Stack Overflow
  • Verified my database schema and migrations
  • Added debugging prints to trace the issue
  • Tested with different data inputs

Environment details:

  • Django version: 5.0.1
  • Python version: 3.11.0
  • Database: PostgreSQL 15
  • Operating system: Ubuntu 22.04

Has anyone encountered this before? Any guidance would be greatly appreciated!

A
Asked by abaditaye
Newbie 45 rep

3 Answers

19

To optimize Django QuerySets and avoid N+1 problems, use select_related() for ForeignKey and OneToOneField, and prefetch_related() for ManyToManyField and reverse ForeignKey:

# Bad: N+1 query problem
for book in Book.objects.all():
    print(book.author.name)  # Each iteration hits the database

# Good: Use select_related for ForeignKey
for book in Book.objects.select_related('author'):
    print(book.author.name)  # Single query with JOIN

# Good: Use prefetch_related for ManyToMany
for book in Book.objects.prefetch_related('categories'):
    for category in book.categories.all():
        print(category.name)  # Optimized with separate query

You can also use only() to limit fields and defer() to exclude heavy fields:

# Only fetch specific fields
Book.objects.only('title', 'author__name').select_related('author')

# Defer heavy fields
Book.objects.defer('content', 'description')
S
Answered by sarah_tech 1 week, 4 days ago
Newbie 45 rep
18

Here's how to optimize Python code performance using profiling tools:

1. Use cProfile for function-level profiling:

import cProfile
import pstats

# Profile your code
cProfile.run('your_function()', 'profile_output.prof')

# Analyze results
stats = pstats.Stats('profile_output.prof')
stats.sort_stats('cumulative')
stats.print_stats(10)  # Top 10 functions

2. Use line_profiler for line-by-line analysis:

# Install: pip install line_profiler
# Add @profile decorator to functions
@profile
def slow_function():
    # Your code here
    pass

# Run: kernprof -l -v script.py

3. Memory profiling with memory_profiler:

# Install: pip install memory_profiler
from memory_profiler import profile

@profile
def memory_intensive_function():
    # Your code here
    pass

# Run: python -m memory_profiler script.py

4. Use timeit for micro-benchmarks:

import timeit

# Compare different approaches
time1 = timeit.timeit('sum([1,2,3,4,5])', number=100000)
time2 = timeit.timeit('sum((1,2,3,4,5))', number=100000)
print(f'List: {time1}, Tuple: {time2}')
W
Answered by william 1 week, 4 days ago
Newbie 40 rep

Comments

lisa_data: Excellent solution! This fixed my Django N+1 query problem immediately. Performance improved by 80%. 1 week, 4 days ago

david_web: Great Python profiling example! The cProfile output helped me identify the bottleneck in my data processing pipeline. 1 week, 4 days ago

10

The difference between threading and multiprocessing in Python is crucial for performance:

Threading (shared memory, GIL limitation):

import threading
import time

def io_bound_task(name):
    print(f'Starting {name}')
    time.sleep(2)  # Simulates I/O operation
    print(f'Finished {name}')

# Good for I/O-bound tasks
threads = []
for i in range(3):
    t = threading.Thread(target=io_bound_task, args=(f'Task-{i}',))
    threads.append(t)
    t.start()

for t in threads:
    t.join()

Multiprocessing (separate memory, no GIL):

import multiprocessing
import time

def cpu_bound_task(name):
    # CPU-intensive calculation
    result = sum(i * i for i in range(1000000))
    return f'{name}: {result}'

# Good for CPU-bound tasks
if __name__ == '__main__':
    with multiprocessing.Pool(processes=4) as pool:
        tasks = [f'Process-{i}' for i in range(4)]
        results = pool.map(cpu_bound_task, tasks)
        print(results)

Concurrent.futures (unified interface):

from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor

# For I/O-bound tasks
with ThreadPoolExecutor(max_workers=4) as executor:
    futures = [executor.submit(io_bound_task, f'Task-{i}') for i in range(4)]
    results = [future.result() for future in futures]

# For CPU-bound tasks
with ProcessPoolExecutor(max_workers=4) as executor:
    futures = [executor.submit(cpu_bound_task, f'Process-{i}') for i in range(4)]
    results = [future.result() for future in futures]
J
Answered by john_doe 1 week, 4 days ago
Bronze 50 rep

Comments

william: This Django transaction approach worked perfectly for my payment processing system. Thanks! 1 week, 4 days ago

abdullah: Could you provide the requirements.txt for the packages used in this solution? 1 week, 4 days ago

Your Answer

You need to be logged in to answer questions.

Log In to Answer