CRUD in Django - potatoscript/django GitHub Wiki
CRUD means:
- π Create something new
- π Read and show data
- βοΈ Update whatβs already there
- β Delete stuff when you donβt need it
With Django, this is actually fun to build! Let's create a small blog-like app to understand everything π±
In models.py
, we make a model called Post
.
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
python manage.py makemigrations
python manage.py migrate
Now Django creates a database table for Post
β
In the Django admin panel or shell:
python manage.py shell
from yourapp.models import Post
Post.objects.create(title='My First Post', content='Hello Django!')
from django.views.generic.edit import CreateView
from django.urls import reverse_lazy
from .models import Post
class PostCreateView(CreateView):
model = Post
fields = ['title', 'content']
template_name = 'post_form.html'
success_url = reverse_lazy('post-list')
path('post/new/', PostCreateView.as_view(), name='post-create'),
<h1>π Create New Post</h1>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Create</button>
</form>
from django.views.generic import ListView
class PostListView(ListView):
model = Post
template_name = 'post_list.html'
context_object_name = 'posts'
path('', PostListView.as_view(), name='post-list'),
π post_list.html
<h1>π All Posts</h1>
<ul>
{% for post in posts %}
<li>
<a href="{% url 'post-detail' post.pk %}">{{ post.title }}</a>
</li>
{% endfor %}
</ul>
<a href="{% url 'post-create' %}">β Add New Post</a>
from django.views.generic import DetailView
class PostDetailView(DetailView):
model = Post
template_name = 'post_detail.html'
path('post/<int:pk>/', PostDetailView.as_view(), name='post-detail'),
π post_detail.html
<h2>{{ object.title }}</h2>
<p>{{ object.content }}</p>
<p><a href="{% url 'post-update' object.pk %}">βοΈ Edit</a></p>
<p><a href="{% url 'post-delete' object.pk %}">β Delete</a></p>
from django.views.generic.edit import UpdateView
class PostUpdateView(UpdateView):
model = Post
fields = ['title', 'content']
template_name = 'post_form.html'
success_url = reverse_lazy('post-list')
path('post/<int:pk>/edit/', PostUpdateView.as_view(), name='post-update'),
β
We reuse the same post_form.html
template!
from django.views.generic.edit import DeleteView
class PostDeleteView(DeleteView):
model = Post
template_name = 'post_confirm_delete.html'
success_url = reverse_lazy('post-list')
path('post/<int:pk>/delete/', PostDeleteView.as_view(), name='post-delete'),
π post_confirm_delete.html
<h2>ποΈ Are you sure you want to delete "{{ object.title }}"?</h2>
<form method="post">
{% csrf_token %}
<button type="submit">Yes, delete</button>
<a href="{% url 'post-list' %}">Cancel</a>
</form>
Action | URL | View | Template |
---|---|---|---|
Create | /post/new/ |
PostCreateView |
post_form.html |
Read All | / |
PostListView |
post_list.html |
Read One | /post/1/ |
PostDetailView |
post_detail.html |
Update | /post/1/edit/ |
PostUpdateView |
post_form.html |
Delete | /post/1/delete/ |
PostDeleteView |
post_confirm_delete.html |
- π Use
LoginRequiredMixin
if users must log in - π¨ Style with Bootstrap or Tailwind CSS
- π§ͺ Test with
python manage.py runserver