| name | django |
| description | Django web framework best practices and patterns |
| license | MIT |
| compatibility | opencode |
| metadata | {"audience":"developers","category":"frameworks"} |
What I do
- Build Django applications following best practices
- Use class-based views for complex logic
- Implement proper model design with migrations
- Handle forms and model forms
- Use Django ORM effectively
- Implement authentication and permissions
- Create REST APIs with Django REST Framework
- Write unit and integration tests
When to use me
When building Django applications or APIs.
Project Structure
myproject/
├── myproject/
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ ├── wsgi.py
│ └── asgi.py
├── apps/
│ ├── users/
│ │ ├── __init__.py
│ │ ├── models.py
│ │ ├── views.py
│ │ ├── urls.py
│ │ ├── serializers.py
│ │ ├── forms.py
│ │ ├── admin.py
│ │ ├── permissions.py
│ │ ├── throttling.py
│ │ ├── apps.py
│ │ └── tests/
│ │ ├── __init__.py
│ │ ├── test_models.py
│ │ └── test_views.py
│ └── posts/
│ └── ...
├── templates/
│ └── base.html
├── static/
│ ├── css/
│ └── js/
├── media/
├── locale/
├── manage.py
├── requirements.txt
├── pytest.ini
└── .env
Models
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.core.validators import MinLengthValidator, URLValidator
from django.utils import timezone
from django.conf import settings
class BaseModel(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
class User(AbstractUser):
email = models.EmailField(unique=True)
bio = models.TextField(max_length=500, blank=True)
avatar = models.ImageField(upload_to='avatars/', null=True, blank=True)
is_verified = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
def __str__(self):
return self.username
class Post(BaseModel):
author = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name='posts'
)
title = models.CharField(max_length=200)
slug = models.SlugField(max_length=200, unique=True)
content = models.TextField()
status = models.CharField(
max_length=,
choices=[(, ), (, )],
default=
)
published_at = models.DateTimeField(null=, blank=)
tags = models.ManyToManyField(, related_name=)
views = models.PositiveIntegerField(default=)
:
ordering = [, ]
indexes = [
models.Index(fields=[]),
models.Index(fields=[, ]),
]
():
.status == .published_at:
.published_at = timezone.now()
().save(*args, **kwargs)
(models.Model):
name = models.CharField(max_length=, unique=)
slug = models.SlugField(max_length=, unique=)
():
.name
Class-Based Views
from django.views.generic import (
ListView, DetailView, CreateView, UpdateView, DeleteView
)
from django.contrib.auth.mixins import LoginRequiredMixin
from django.urls import reverse_lazy
from django.core.exceptions import PermissionDenied
from rest_framework.generics import ListAPIView
class PostListView(ListView):
model = Post
template_name = 'posts/list.html'
context_object_name = 'posts'
paginate_by = 10
def get_queryset(self):
return Post.objects.filter(
status='published'
).select_related('author').prefetch_related('tags')
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['page_title'] = 'All Posts'
return context
class PostDetailView(DetailView):
model = Post
template_name = 'posts/detail.html'
context_object_name = 'post'
def get_queryset(self):
return Post.objects.select_related('author').prefetch_related('tags')
class PostCreateView(LoginRequiredMixin, CreateView):
model = Post
fields = [, , ]
template_name =
success_url = reverse_lazy()
():
form.instance.author = .request.user
().form_valid(form)
(LoginRequiredMixin, UpdateView):
model = Post
fields = [, , ]
template_name =
():
Post.objects.(author=.request.user)
():
post = ().get_object()
post.author != .request.user:
PermissionDenied
post
(LoginRequiredMixin, DeleteView):
model = Post
success_url = reverse_lazy()
():
Post.objects.(author=.request.user)
Django REST Framework
from rest_framework import serializers, viewsets, permissions
from drf_spectacular.utils import extend_schema, OpenApiParameter
from drf_spectacular.types import OpenApiTypes
class PostSerializer(serializers.ModelSerializer):
author = serializers.ReadOnlyField(source='author.username')
tags = serializers.SlugRelatedField(many=True, read_only=True, slug_field='name')
class Meta:
model = Post
fields = [
'id', 'title', 'slug', 'content', 'author',
'status', 'published_at', 'tags', 'views',
'created_at', 'updated_at'
]
read_only_fields = ['id', 'slug', 'author', 'views', 'created_at', 'updated_at']
@extend_schema(
parameters=[
OpenApiParameter(name='search', description='Search in title and content'),
OpenApiParameter(name='status', description='Filter by status'),
]
)
class PostViewSet(viewsets.ModelViewSet):
serializer_class = PostSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
lookup_field = 'slug'
def get_queryset():
queryset = Post.objects.select_related().prefetch_related()
status = .request.query_params.get()
status:
queryset = queryset.(status=status)
search = .request.query_params.get()
search:
queryset = queryset.(title__icontains=search)
queryset
():
serializer.save(author=.request.user)
django.urls path, include
rest_framework.routers DefaultRouter
router = DefaultRouter()
router.register(, PostViewSet, basename=)
urlpatterns = [
path(, include(router.urls)),
]