Views handle HTTP requests and return responses. Django supports function-based views (FBVs) and class-based views (CBVs).

Function-Based Views

  # blog/views.py
from django.shortcuts import render, get_object_or_404
from .models import Post

def post_list(request):
    posts = Post.objects.filter(published=True)
    return render(request, 'blog/post_list.html', {'posts': posts})

def post_detail(request, pk):
    post = get_object_or_404(Post, pk=pk, published=True)
    return render(request, 'blog/post_detail.html', {'post': post})
  

URL Routing

  # blog/urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('', views.post_list, name='post_list'),
    path('<int:pk>/', views.post_detail, name='post_detail'),
]
  

Templates

Create blog/templates/blog/post_list.html:

  {% extends "base.html" %}

{% block content %}
<h1>Blog Posts</h1>
{% for post in posts %}
  <article>
    <h2><a href="{% url 'post_detail' post.pk %}">{{ post.title }}</a></h2>
    <p>{{ post.content|truncatewords:30 }}</p>
    <time>{{ post.created_at|date:"M d, Y" }}</time>
  </article>
{% empty %}
  <p>No posts yet.</p>
{% endfor %}
{% endblock %}
  

Template Inheritance

  <!-- templates/base.html -->
<!DOCTYPE html>
<html>
<head>
  <title>{% block title %}My Blog{% endblock %}</title>
</head>
<body>
  <nav><a href="{% url 'post_list' %}">Home</a></nav>
  {% block content %}{% endblock %}
</body>
</html>
  

Class-Based Views

CBVs reduce boilerplate for common patterns:

  from django.views.generic import ListView, DetailView

class PostListView(ListView):
    model = Post
    template_name = 'blog/post_list.html'
    context_object_name = 'posts'
    queryset = Post.objects.filter(published=True)

class PostDetailView(DetailView):
    model = Post
    template_name = 'blog/post_detail.html'
    context_object_name = 'post'
  
  # urls.py
from django.views.generic import ListView
from .views import PostListView, PostDetailView

urlpatterns = [
    path('', PostListView.as_view(), name='post_list'),
    path('<int:pk>/', PostDetailView.as_view(), name='post_detail'),
]
  

Forms

  from django import forms
from .models import Post

class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = ['title', 'content', 'published']

# In a view
def create_post(request):
    if request.method == 'POST':
        form = PostForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('post_list')
    else:
        form = PostForm()
    return render(request, 'blog/post_form.html', {'form': form})
  

Views and templates together deliver the user-facing experience of your Django application.