Install
$ agentstack add skill-sufficientdaikon-archon-django-framework ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ● Filesystem access Used
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Django Framework Skill
progressivedisclosure: entrypoint: summary: "Full-featured Python web framework with batteries included (ORM, admin, auth)" whentouse:
- "When building content-heavy web applications"
- "When needing built-in admin interface"
- "When using Django ORM and migrations"
- "When building REST APIs with Django REST Framework"
quick_start:
- "pip install django"
- "django-admin startproject myproject"
- "python manage.py runserver"
token_estimate: entry: 75-90 full: 4500-5500 ---
Overview
Django is a high-level Python web framework that encourages rapid development and clean, pragmatic design. Built by experienced developers, it takes care of much of the hassle of web development, enabling focus on writing applications without reinventing the wheel.
Key Philosophy: "Batteries included" - Django comes with extensive built-in features including ORM, authentication, admin interface, forms, and security features.
Core Concepts
MVT Architecture (Model-View-Template)
Django follows the MVT pattern:
- Model: Data layer (ORM models, database schema)
- View: Business logic (handles requests, returns responses)
- Template: Presentation layer (HTML with Django template language)
Project vs Apps
- Project: The entire Django application (settings, URLs, WSGI config)
- Apps: Modular components (blog, auth, API) that can be reused across projects
# Create project
django-admin startproject myproject
cd myproject
# Create app
python manage.py startapp blog
# Register app in settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
# ...
'blog',
]
Models and ORM
Model Definition
# models.py
from django.db import models
from django.contrib.auth.models import User
class Category(models.Model):
name = models.CharField(max_length=100, unique=True)
slug = models.SlugField(unique=True)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name_plural = "categories"
ordering = ['name']
def __str__(self):
return self.name
class Post(models.Model):
STATUS_CHOICES = [
('draft', 'Draft'),
('published', 'Published'),
]
title = models.CharField(max_length=200)
slug = models.SlugField(unique=True)
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='posts')
category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True)
content = models.TextField()
status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='draft')
published_at = models.DateTimeField(null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['-published_at']
indexes = [
models.Index(fields=['-published_at']),
models.Index(fields=['slug']),
]
def __str__(self):
return self.title
Common Field Types
# Text fields
models.CharField(max_length=200)
models.TextField()
models.SlugField()
models.EmailField()
models.URLField()
# Numeric fields
models.IntegerField()
models.DecimalField(max_digits=10, decimal_places=2)
models.FloatField()
# Date/time fields
models.DateField()
models.DateTimeField()
models.DurationField()
# Boolean
models.BooleanField(default=False)
# Relationships
models.ForeignKey(Model, on_delete=models.CASCADE)
models.ManyToManyField(Model)
models.OneToOneField(Model, on_delete=models.CASCADE)
# Files
models.FileField(upload_to='uploads/')
models.ImageField(upload_to='images/')
# JSON (PostgreSQL)
models.JSONField()
Migrations
# Create migrations after model changes
python manage.py makemigrations
# View SQL that will be executed
python manage.py sqlmigrate blog 0001
# Apply migrations
python manage.py migrate
# Create empty migration for custom operations
python manage.py makemigrations --empty blog
# Reverse migration
python manage.py migrate blog 0001
QuerySet API
# Basic queries
Post.objects.all()
Post.objects.filter(status='published')
Post.objects.exclude(status='draft')
Post.objects.get(pk=1) # Returns single object or raises DoesNotExist
# Chaining filters
Post.objects.filter(status='published').filter(category__name='Tech')
# Field lookups
Post.objects.filter(title__icontains='django') # Case-insensitive contains
Post.objects.filter(published_at__year=2024)
Post.objects.filter(published_at__gte=datetime(2024, 1, 1))
Post.objects.filter(author__username__startswith='john')
# Ordering
Post.objects.order_by('-published_at')
Post.objects.order_by('category', '-created_at')
# Limiting
Post.objects.all()[:5] # First 5
Post.objects.all()[5:10] # Offset pagination
# Aggregation
from django.db.models import Count, Avg, Sum
Category.objects.annotate(post_count=Count('post'))
Post.objects.aggregate(avg_length=Avg('content__length'))
# Q objects for complex queries
from django.db.models import Q
Post.objects.filter(Q(status='published') | Q(author=request.user))
Post.objects.filter(Q(status='published') & ~Q(category=None))
# F expressions for field comparisons
from django.db.models import F
Post.objects.filter(updated_at__gt=F('published_at'))
# Select/Prefetch related (performance optimization)
Post.objects.select_related('author', 'category') # SQL JOIN
Post.objects.prefetch_related('tags') # Separate query for M2M
Model Methods and Properties
class Post(models.Model):
# ... fields ...
@property
def is_published(self):
return self.status == 'published' and self.published_at is not None
def get_absolute_url(self):
from django.urls import reverse
return reverse('post_detail', kwargs={'slug': self.slug})
def save(self, *args, **kwargs):
# Auto-generate slug if not provided
if not self.slug:
from django.utils.text import slugify
self.slug = slugify(self.title)
super().save(*args, **kwargs)
class Meta:
verbose_name = "blog post"
verbose_name_plural = "blog posts"
Views
Function-Based Views (FBV)
# views.py
from django.shortcuts import render, get_object_or_404, redirect
from django.http import JsonResponse, HttpResponse
from django.contrib.auth.decorators import login_required
from .models import Post
from .forms import PostForm
def post_list(request):
posts = Post.objects.filter(status='published').select_related('author', 'category')
context = {'posts': posts}
return render(request, 'blog/post_list.html', context)
def post_detail(request, slug):
post = get_object_or_404(Post, slug=slug, status='published')
return render(request, 'blog/post_detail.html', {'post': post})
@login_required
def post_create(request):
if request.method == 'POST':
form = PostForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
post.save()
return redirect('post_detail', slug=post.slug)
else:
form = PostForm()
return render(request, 'blog/post_form.html', {'form': form})
def api_posts(request):
posts = Post.objects.filter(status='published').values('title', 'slug', 'published_at')
return JsonResponse(list(posts), safe=False)
Class-Based Views (CBV)
# views.py
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.urls import reverse_lazy
from .models import Post
class PostListView(ListView):
model = Post
template_name = 'blog/post_list.html'
context_object_name = 'posts'
paginate_by = 10
def get_queryset(self):
return Post.objects.filter(status='published').select_related('author', 'category')
class PostDetailView(DetailView):
model = Post
template_name = 'blog/post_detail.html'
context_object_name = 'post'
def get_queryset(self):
return Post.objects.filter(status='published')
class PostCreateView(LoginRequiredMixin, CreateView):
model = Post
form_class = PostForm
template_name = 'blog/post_form.html'
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
class PostUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = Post
form_class = PostForm
template_name = 'blog/post_form.html'
def test_func(self):
post = self.get_object()
return self.request.user == post.author
class PostDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
model = Post
success_url = reverse_lazy('post_list')
def test_func(self):
post = self.get_object()
return self.request.user == post.author
URLs and Routing
# project/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('blog/', include('blog.urls')),
path('api/', include('api.urls')),
]
# blog/urls.py
from django.urls import path
from . import views
app_name = 'blog'
urlpatterns = [
path('', views.PostListView.as_view(), name='post_list'),
path('post//', views.PostDetailView.as_view(), name='post_detail'),
path('post/create/', views.PostCreateView.as_view(), name='post_create'),
path('post//edit/', views.PostUpdateView.as_view(), name='post_update'),
path('post//delete/', views.PostDeleteView.as_view(), name='post_delete'),
# Function-based views
path('api/posts/', views.api_posts, name='api_posts'),
]
Templates
Template Syntax
{# blog/templates/blog/post_list.html #}
{% extends 'base.html' %}
{% load static %}
{% block title %}Blog Posts{% endblock %}
{% block content %}
Blog Posts
{% if posts %}
{% for post in posts %}
{{ post.title }}
By {{ post.author.username }} on {{ post.published_at|date:"F d, Y" }}
in {{ post.category.name }}
{{ post.content|truncatewords:50 }}
{% empty %}
No posts found.
{% endfor %}
{# Pagination #}
{% if is_paginated %}
{% if page_obj.has_previous %}
First
Previous
{% endif %}
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}
{% if page_obj.has_next %}
Next
Last
{% endif %}
{% endif %}
{% else %}
No posts available.
{% endif %}
{% endblock %}
Template Filters and Tags
{# Common filters #}
{{ value|lower }}
{{ value|upper }}
{{ value|title }}
{{ value|truncatewords:30 }}
{{ value|date:"Y-m-d" }}
{{ value|default:"N/A" }}
{{ html_content|safe }} {# Disable auto-escaping #}
{{ url|urlencode }}
{# Custom template tag #}
{% load custom_tags %}
{% get_recent_posts 5 as recent %}
{# Include other templates #}
{% include 'blog/partials/post_card.html' with post=post %}
{# Static files #}
Forms
Form Definition
# forms.py
from django import forms
from .models import Post, Category
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ['title', 'slug', 'category', 'content', 'status']
widgets = {
'content': forms.Textarea(attrs={'rows': 10}),
'slug': forms.TextInput(attrs={'placeholder': 'auto-generated-if-empty'}),
}
def clean_slug(self):
slug = self.cleaned_data.get('slug')
if slug and Post.objects.filter(slug=slug).exclude(pk=self.instance.pk).exists():
raise forms.ValidationError('This slug is already in use.')
return slug
class ContactForm(forms.Form):
name = forms.CharField(max_length=100)
email = forms.EmailField()
subject = forms.CharField(max_length=200)
message = forms.CharField(widget=forms.Textarea)
def clean_email(self):
email = self.cleaned_data.get('email')
if email and not email.endswith('@example.com'):
raise forms.ValidationError('Please use your company email.')
return email
def send_email(self):
# Send email logic
pass
Form Usage in Views
def contact_view(request):
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
form.send_email()
messages.success(request, 'Message sent successfully!')
return redirect('contact_success')
else:
form = ContactForm()
return render(request, 'contact.html', {'form': form})
Form Rendering in Templates
{% csrf_token %}
{# Auto-render all fields #}
{{ form.as_p }}
{# Manual field rendering #}
{{ form.title.label_tag }}
{{ form.title }}
{% if form.title.errors %}
{{ form.title.errors }}
{% endif %}
Submit
Django Admin
Basic Admin Configuration
# admin.py
from django.contrib import admin
from .models import Post, Category
@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
list_display = ['name', 'slug', 'created_at']
prepopulated_fields = {'slug': ('name',)}
search_fields = ['name']
@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
list_display = ['title', 'author', 'category', 'status', 'published_at']
list_filter = ['status', 'category', 'created_at']
search_fields = ['title', 'content']
prepopulated_fields = {'slug': ('title',)}
date_hierarchy = 'published_at'
ordering = ['-published_at']
fieldsets = (
('Basic Information', {
'fields': ('title', 'slug', 'author', 'category')
}),
('Content', {
'fields': ('content',)
}),
('Publication', {
'fields': ('status', 'published_at')
}),
)
def get_queryset(self, request):
qs = super().get_queryset(request)
return qs.select_related('author', 'category')
Advanced Admin Features
class PostAdmin(admin.ModelAdmin):
# Custom actions
actions = ['make_published', 'make_draft']
def make_published(self, request, queryset):
updated = queryset.update(status='published')
self.message_user(request, f'{updated} posts marked as published.')
make_published.short_description = "Mark selected posts as published"
# Inline editing
class TagInline(admin.TabularInline):
model = Post.tags.through
extra = 1
inlines = [TagInline]
# Custom methods in list_display
def author_email(self, obj):
return obj.author.email
author_email.short_description = 'Author Email'
list_display = ['title', 'author', 'author_email', 'status']
Authentication and Permissions
User Authentication
# views.py
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.decorators import login_required, permission_required
def login_view(request):
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
return redirect('home')
return render(request, 'login.html')
def logout_view(request):
logout(request)
return redirect('home')
def register_view(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
…
## Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- **Author:** [SufficientDaikon](https://github.com/SufficientDaikon)
- **Source:** [SufficientDaikon/archon](https://github.com/SufficientDaikon/archon)
- **License:** MIT
- **Homepage:** https://sufficientdaikon.github.io/archon/
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.