Models, Views & URLs
Models, Views & URLs Project Setup pip install django djangorestframework django-admin startproject myproject . python manage.py startapp users # Run dev server…
Models, Views & URLs
Project Setup
pip install django djangorestframework
django-admin startproject myproject .
python manage.py startapp users
# Run dev server
python manage.py runserver
# Migrations
python manage.py makemigrations
python manage.py migrate
python manage.py createsuperuser
# Shell
python manage.py shellModels
# users/models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
bio = models.TextField(blank=True)
avatar = models.ImageField(upload_to='avatars/', null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
class Category(models.Model):
name = models.CharField(max_length=100, unique=True)
slug = models.SlugField(unique=True)
class Meta:
verbose_name_plural = 'categories'
ordering = ['name']
def __str__(self):
return self.name
class Post(models.Model):
STATUS_DRAFT = 'draft'
STATUS_PUBLISHED = 'published'
STATUS_CHOICES = [
(STATUS_DRAFT, 'Draft'),
(STATUS_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)
tags = models.ManyToManyField('Tag', blank=True)
body = models.TextField()
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default=STATUS_DRAFT)
view_count = models.PositiveIntegerField(default=0)
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 = ['-created_at']
indexes = [models.Index(fields=['status', '-created_at'])]
def __str__(self):
return self.title
# Field types reference
# CharField, TextField, IntegerField, FloatField, DecimalField
# BooleanField, DateField, DateTimeField, EmailField, URLField
# ForeignKey, OneToOneField, ManyToManyField
# ImageField, FileField, JSONField
# on_delete: CASCADE, SET_NULL, SET_DEFAULT, PROTECT, DO_NOTHINGORM Queries
from users.models import Post, User
# Create
post = Post.objects.create(title='Hello', author=user, slug='hello')
post = Post(title='Hello', author=user)
post.save()
# Read
Post.objects.all()
Post.objects.filter(status='published')
Post.objects.filter(author__username='alice') # traverse FK
Post.objects.filter(title__icontains='hello') # field lookup
Post.objects.filter(created_at__gte=datetime(2024, 1, 1))
Post.objects.exclude(status='draft')
Post.objects.get(id=1) # raises DoesNotExist if not found
Post.objects.get_or_create(slug='hello', defaults={'title': 'Hello'})
# Chaining
Post.objects.filter(status='published').order_by('-created_at')[:10]
Post.objects.select_related('author', 'category') # JOIN (ForeignKey)
Post.objects.prefetch_related('tags') # separate query (M2M)
# Aggregation
from django.db.models import Count, Avg, Sum, Max, Q
Post.objects.filter(status='published').count()
Post.objects.aggregate(avg_views=Avg('view_count'))
Post.objects.values('author__username').annotate(post_count=Count('id'))
# Q objects — complex queries
Post.objects.filter(Q(status='published') | Q(author=user))
Post.objects.filter(Q(status='published') & ~Q(category=None))
# Update
Post.objects.filter(author=user).update(status='published')
# post.save() — always triggers signals; .update() does not
# Delete
Post.objects.filter(status='draft', created_at__lt=cutoff).delete()Views & URLs
# views.py (function-based)
from django.shortcuts import render, get_object_or_404, redirect
from django.http import JsonResponse
from django.contrib.auth.decorators import login_required
def post_list(request):
posts = Post.objects.filter(status='published').select_related('author')
return render(request, 'posts/list.html', {'posts': posts})
def post_detail(request, slug):
post = get_object_or_404(Post, slug=slug, status='published')
return render(request, 'posts/detail.html', {'post': post})
@login_required
def create_post(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, 'posts/form.html', {'form': form})
# urls.py
from django.urls import path, include
from . import views
urlpatterns = [
path('', views.post_list, name='post_list'),
path('<slug:slug>/', views.post_detail, name='post_detail'),
path('create/', views.create_post, name='create_post'),
]
# myproject/urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('posts/', include('posts.urls')),
path('api/', include('api.urls')),
]