6 Django Mistakes That Expose You as a Rookie! 🚨 [Part 2]

This is the second part of 6 Django Mistakes That Expose You as a Rookie! 🚨 . If you haven’t checkout the Part 1 do checkout by clicking…

6 Django Mistakes That Expose You as a Rookie! 🚨 [Part 2]
Photo by Francisco De Legarreta C. on Unsplash

This is the second part of 6 Django Mistakes That Expose You as a Rookie! 🚨 . If you haven’t checkout the Part 1 do checkout by clicking the link below :

6 Django Mistakes That Expose You as a Rookie! 🚨
Photo by Francisco De Legarreta C. on Unsplash

In this article will again going to discuss 6 Django Mistakes That Expose You as a Rookie!


1. Not Using get_object_or_404 for Retrieving Single Objects

Beginners often use filter().first() or try-except blocks to get objects, leading to unnecessary database hits or incorrect error handling.

Bad Practice: Manually Handling Query Failures

def get_product(request, product_id): 
    try: 
        product = Product.objects.get(id=product_id) 
    except Product.DoesNotExist: 
        return HttpResponseNotFound("Product not found")

This is unnecessary and verbose.

Best Practice: Use get_object_or_404

from django.shortcuts import get_object_or_404 
 
def get_product(request, product_id): 
    product = get_object_or_404(Product, id=product_id)

This looks Cleaner code and automatically raises a 404 error if the object isn’t found.

2. Hardcoding URLs Instead of Using reverse() or {% url %}

Manually writing URLs makes code brittle — changing one URL requires updating multiple files.

Bad Practice: Hardcoding URLs

<a href="/products/123/">View Product</a>

I do the same mistake when i was new to Django.

Best Practice: Use {% url %} in Templates

<a href="{% url 'product-detail' product.id %}">View Product</a>

Or in Django views:

from django.urls import reverse 
 
url = reverse("product-detail", args=[product.id])

This will Automatically updates URLs when routes change and Reduces maintenance overhead.

If you need both select_related (ForeignKey optimization) and prefetch_related (ManyToMany optimization), use preload_related instead.

Bad Practice: Using Separate Calls

orders = Order.objects.select_related("customer").prefetch_related("items")

Here, Django first fetches ForeignKey objects and then makes additional queries for ManyToMany.

orders = Order.objects.preload_related("customer", "items")

This will Optimizes related queries in a single call and Reduces database hits.

4. Forgetting to Add CSRF Protection in Forms

Django has built-in Cross-Site Request Forgery (CSRF) protection, but some developers forget to use it, making their app vulnerable to attacks.

Bad Practice: No CSRF Token in Forms

<form method="POST" action="/submit/"> 
    <input type="text" name="name"> 
    <button type="submit">Submit</button> 
</form>

This form isn’t protected from CSRF attacks.

Best Practice: Always Include {% csrf_token %}

<form method="POST" action="{% url 'submit' %}"> 
    {% csrf_token %} 
    <input type="text" name="name"> 
    <button type="submit">Submit</button> 
</form>

This will Prevents CSRF attacks and Ensures form submissions are secure.

5. Overusing print() for Debugging Instead of Django’s Logging System

Many beginners rely on print() to debug, but it doesn’t work well in production and lacks structured logging.

Bad Practice: Using print() for Debugging

def my_view(request): 
    print("Processing request...")  # Unhelpful in production! 
    return HttpResponse("Hello")

This won’t log errors in production.

Best Practice: Use Django’s Logging System

import logging 
 
logger = logging.getLogger(__name__) 
 
def my_view(request): 
    logger.info("Processing request...") 
    return HttpResponse("Hello")

This Stores logs properly in production and allows different log levels (info, warning, error, critical).

6. Using Inline Queries Instead of Custom Managers

If you repeat queries everywhere in views, you should use a custom manager instead.

Bad Practice: Duplicating Queries in Views

def active_products(): 
    return Product.objects.filter(is_active=True)

Instead of copying this query across multiple files, use a custom manager.

Best Practice: Use a Custom Model Manager

class ProductManager(models.Manager): 
    def active(self): 
        return self.filter(is_active=True) 
 
class Product(models.Model): 
    name = models.CharField(max_length=255) 
    is_active = models.BooleanField(default=True) 
 
    objects = ProductManager()

Now, call it like this:

products = Product.objects.active()

This will Keeps queries reusable and DRY (Don’t Repeat Yourself) and Improves maintainability.


Final Thoughts

By avoiding these common Django mistakes, you’ll write cleaner, more efficient code and improve your app’s performance, security, and maintainability.

Which mistake have you made before? Let me know in the comments! 🚀


If you find this article helpful, i am sure you will also love the part 1

6 Django Mistakes That Expose You as a Rookie! 🚨
Photo by Francisco De Legarreta C. on Unsplash
Photo by Matt Halls on Unsplash