| name | django-application |
| description | Develop production-grade Django applications with models, views, ORM queries, authentication, and admin interfaces. Use when building web applications, managing databases with Django ORM, and implementing authentication systems. |
Django Application
Overview
Build comprehensive Django web applications with proper model design, view hierarchies, database operations, user authentication, and admin functionality following Django conventions and best practices.
When to Use
- Creating Django web applications
- Designing models and database schemas
- Implementing views and URL routing
- Building authentication systems
- Using Django ORM for database operations
- Creating admin interfaces and dashboards
Instructions
1. Django Project Setup
django-admin startproject myproject
cd myproject
python manage.py startapp users
python manage.py startapp products
2. Model Design with ORM
# users/models.py
from django.contrib.auth.models import AbstractUser
from django.db import models
from django.contrib.auth import get_user_model
class CustomUser(AbstractUser):
ROLE_CHOICES = [
('admin', 'Administrator'),
('user', 'Regular User'),
]
profile_picture = models.ImageField(upload_to='profiles/', null=True)
role = models.CharField(max_length=20, choices=ROLE_CHOICES, default='user')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['-created_at']
indexes = [
models.Index(fields=['email']),
models.Index(fields=['role']),
]
def __str__(self):
return self.email
# products/models.py
User = get_user_model()
class Product(models.Model):
STATUS_CHOICES = [
('draft', 'Draft'),
('published', 'Published'),
]
title = models.CharField(max_length=200, db_index=True)
slug = models.SlugField(unique=True)
description = models.TextField()
price = models.DecimalField(max_digits=10, decimal_places=2)
stock = models.PositiveIntegerField(default=0)
status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='draft')
owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name='products')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['-created_at']
unique_together = ['slug', 'owner']
def __str__(self):
return self.title
class ProductReview(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='reviews')
author = models.ForeignKey(User, on_delete=models.CASCADE)
rating = models.IntegerField(choices=[(i, i) for i in range(1, 6)])
comment = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
unique_together = ['product', 'author']
3. Views with Class-Based and Function-Based Approaches
# products/views.py
from django.views import View
from django.views.generic import ListView, DetailView, CreateView
from django.contrib.auth.mixins import LoginRequiredMixin
from django.shortcuts import render, redirect, get_object_or_404
from django.http import JsonResponse
from django.db.models import Q, Count, Avg
from rest_framework import viewsets, status
from rest_framework.response import Response
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated
from .models import Product, ProductReview
from .serializers import ProductSerializer
# Class-based view with authentication
class ProductListView(LoginRequiredMixin, ListView):
model = Product
template_name = 'products/list.html'
context_object_name = 'products'
paginate_by = 20
def get_queryset(self):
queryset = Product.objects.filter(status='published')
# Search and filter
search = self.request.GET.get('q')
if search:
queryset = queryset.filter(
Q(title__icontains=search) | Q(description__icontains=search)
)
# Price range filter
min_price = self.request.GET.get('min_price')
max_price = self.request.GET.get('max_price')
if min_price:
queryset = queryset.filter(price__gte=min_price)
if max_price:
queryset = queryset.filter(price__lte=max_price)
return queryset.annotate(
review_count=Count('reviews'),
avg_rating=Avg('reviews__rating')
).order_by('-created_at')
# REST API ViewSet
class ProductViewSet(viewsets.ModelViewSet):
permission_classes = [IsAuthenticated]
serializer_class = ProductSerializer
queryset = Product.objects.all()
def get_queryset(self):
return Product.objects.filter(owner=self.request.user)
@action(detail=True, methods=['post'])
def add_review(self, request, pk=None):
product = self.get_object()
serializer = ProductReviewSerializer(data=request.data)
if serializer.is_valid():
serializer.save(product=product, author=request.user)
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@action(detail=True, methods=['get'])
def reviews(self, request, pk=None):
product = self.get_object()
reviews = product.reviews.all()
serializer = ProductReviewSerializer(reviews, many=True)
return Response(serializer.data)
4. Authentication and Permissions
# users/views.py
from django.contrib.auth import authenticate, login, logout
from django.views.decorators.http import require_http_methods
from django.views.decorators.csrf import csrf_protect
from rest_framework.authtoken.models import Token
from rest_framework.permissions import BasePermission
class IsOwner(BasePermission):
def has_object_permission(self, request, view, obj):
return obj.owner == request.user
@require_http_methods(['POST'])
@csrf_protect
def login_view(request):
email = request.POST.get('email')
password = request.POST.get('password')
user = authenticate(request, username=email, password=password)
if user is not None:
login(request, user)
token, created = Token.objects.get_or_create(user=user)
return JsonResponse({
'success': True,
'token': token.key,
'user_id': user.id
})
return JsonResponse({'error': 'Invalid credentials'}, status=401)
@require_http_methods(['POST'])
def logout_view(request):
logout(request)
return JsonResponse({'success': True})
5. Database Queries and Optimization
# products/queries.py
from django.db.models import Q, Count, Avg, F, Case, When, Value
from django.db.models.functions import Coalesce
from .models import Product, ProductReview
# Optimized queries with select_related and prefetch_related
def get_product_details(product_id):
return Product.objects.select_related('owner').prefetch_related(
'reviews__author'
).get(id=product_id)
# Aggregation queries
def get_top_products():
return Product.objects.annotate(
review_count=Count('reviews'),
avg_rating=Avg('reviews__rating'),
total_reviews=Count('reviews', distinct=True)
).filter(review_count__gt=0).order_by('-avg_rating')[:10]
# Complex filtering
def search_products(query, category=None, min_price=None, max_price=None):
queryset = Product.objects.filter(
Q(title__icontains=query) | Q(description__icontains=query)
)
if category:
queryset = queryset.filter(category=category)
if min_price:
queryset = queryset.filter(price__gte=min_price)
if max_price:
queryset = queryset.filter(price__lte=max_price)
return queryset.select_related('owner')
# Bulk operations
def bulk_update_stock(updates):
products_to_update = []
for product_id, new_stock in updates.items():
product = Product.objects.get(id=product_id)
product.stock = new_stock
products_to_update.append(product)
Product.objects.bulk_update(products_to_update, ['stock'])
6. URL Routing
# myproject/urls.py
from django.contrib import admin
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from rest_framework.authtoken.views import obtain_auth_token
from products.views import ProductViewSet
router = DefaultRouter()
router.register(r'products', ProductViewSet)
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include(router.urls)),
path('api-token-auth/', obtain_auth_token),
]
7. Admin Interface Customization
# products/admin.py
from django.contrib import admin
from .models import Product, ProductReview
@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
list_display = ['title', 'price', 'stock', 'status', 'owner', 'created_at']
list_filter = ['status', 'created_at', 'owner']
search_fields = ['title', 'description']
readonly_fields = ['created_at', 'updated_at']
fieldsets = (
('Basic Info', {
'fields': ('title', 'slug', 'owner')
}),
('Details', {
'fields': ('description', 'price', 'stock', 'status')
}),
('Metadata', {
'fields': ('created_at', 'updated_at'),
'classes': ('collapse',)
}),
)
def save_model(self, request, obj, form, change):
if not change:
obj.owner = request.user
super().save_model(request, obj, form, change)
@admin.register(ProductReview)
class ProductReviewAdmin(admin.ModelAdmin):
list_display = ['product', 'author', 'rating', 'created_at']
list_filter = ['rating', 'created_at']
readonly_fields = ['created_at']
Best Practices
✅ DO
- Use models for database operations
- Implement proper indexes on frequently queried fields
- Use select_related and prefetch_related for query optimization
- Implement authentication and permissions
- Use Django Forms for form validation
- Cache expensive queries
- Use management commands for batch operations
- Implement logging for debugging
- Use middleware for cross-cutting concerns
- Validate user input
❌ DON'T
- Use raw SQL without ORM
- N+1 query problems without optimization
- Store secrets in code
- Trust user input directly
- Override init in models unnecessarily
- Make synchronous heavy operations in views
- Use inheritance models unless necessary
- Expose stack traces in production
Complete Example
# settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'rest_framework',
'users',
'products'
]
AUTH_USER_MODEL = 'users.CustomUser'
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication',
],
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
]
}
# models.py + views.py (see sections above)
# urls.py + admin.py (see sections above)