Django Blog - 03. 表单

新建博客

导航栏增加新建博客的链接

修改templates/base.html文件,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{% load static %}
<html>
<head>
<title>Django blog</title>
<link rel="stylesheet" href="{% static 'css/base.css' %}">
</head>
<body>
<div class="container">
<header>
<div class="nav-left">
<h1><a href="/">Django blog</a></h1>
</div>
<div class="nav-right">
<h1><a href="{% url 'post_new' %}">+ New Blog Post</a></h1>
</div>
</header>
</div>
<div class="container">
{% block content %}
{% endblock content %}
</div>
</body>
</html>

更新路由

修改blog/urls.py文件,添加新的 URL 配置,代码如下:

1
2
3
4
5
6
7
8
9
from django.urls import path

from . import views

urlpatterns = [
path('', views.BlogListView.as_view(), name='home'),
path('post/<int:pk>/', views.BlogDetailView.as_view(), name='post_detail'),
path('post/new/', views.BlogCreateView.as_view(), name='post_new'),
]

新建视图类

修改blog/views.py文件,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from django.views.generic import ListView, DetailView
from django.views.generic.edit import CreateView
from .models import Post

class BlogListView(ListView):
model = Post
template_name = 'home.html'

class BlogDetailView(DetailView):
model = Post
template_name = 'post_detail.html'

class BlogCreateView(CreateView):
model = Post
template_name = 'post_new.html'
fields = '__all__'

新建模板文件

新建templates/post_new.html文件,代码如下:

1
2
3
4
5
6
7
8
9
{% extends 'base.html' %}

{% block content %}
<h1>New post</h1>
<form action="" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Save">
</form>
{% endblock %}

get_absolute_url

在提交表单之后,Django 需要知道页面要跳转到哪里,为此,可以通过在模型类中提供get_absolute_url方法实现,修改blog/models.py文件,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from django.db import models
from django.urls import reverse

class Post(models.Model):
title = models.CharField(max_length=140)
author = models.ForeignKey(
'auth.User',
on_delete=models.CASCADE,
)
body = models.TextField()

def __str__(self):
"""The representation string of the model"""
return self.title

def get_absolute_url(self):
return reverse('post_detail', args=[str(self.id)])

reverse是 Django 提供的一个方便的函数,只需要通过传入需要重定向的 URL 模板的名字,和所需的参数。

更新博客

添加更新链接

修改templates/post_detail.html文件,代码如下:

1
2
3
4
5
6
7
8
9
{% extends 'base.html' %}

{% block content %}
<div class="post-entry">
<h2>{{ post.title }}</h2>
<p>{{ post.body }}</p>
</div>
<a href="url 'post_edit' post.pk">+Edit Blog Post</a>
{% endblock content %}

新建模板文件

接着,创建templates/post_edit.html文件,代码如下:

1
2
3
4
5
6
7
8
9
{% extends 'base.html' %}

{% block content %}
<h1>Edit post</h1>
<form action="" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Update">
</form>
{% endblock %}

新建视图类

修改blog/views.py文件,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from django.views.generic import ListView, DetailView
from django.views.generic.edit import CreateView, UpdateView
from .models import Post

class BlogListView(ListView):
model = Post
template_name = 'home.html'

class BlogDetailView(DetailView):
model = Post
template_name = 'post_detail.html'

class BlogCreateView(CreateView):
model = Post
template_name = 'post_new.html'
fields = '__all__'

class BlogUpdateView(UpdateView):
model = Post
template_name = 'post_edit.html'
fields = ['title', 'body']

更新路由

修改blog/urls.py文件,添加新的 URL 配置,代码如下:

1
2
3
4
5
6
7
8
9
10
from django.urls import path

from . import views

urlpatterns = [
path('', views.BlogListView.as_view(), name='home'),
path('post/<int:pk>/', views.BlogDetailView.as_view(), name='post_detail'),
path('post/new/', views.BlogCreateView.as_view(), name='post_new'),
path('post/<int:pk>/edit/', views.BlogUpdateView.as_view(), name='post_edit'),
]

删除博客

添加删除链接

修改templates/post_detail.html文件,代码如下:

1
2
3
4
5
6
7
8
9
10
{% extends 'base.html' %}

{% block content %}
<div class="post-entry">
<h2>{{ post.title }}</h2>
<p>{{ post.body }}</p>
</div>
<p><a href="{% url 'post_edit' post.pk %}">+Edit Blog Post</a></p>
<p><a href="{% url 'post_delete' post.pk %}">+Delete Blog Post</a></p>
{% endblock content %}

新建模板文件

接着,创建templates/post_delete.html文件,代码如下:

1
2
3
4
5
6
7
8
9
{% extends 'base.html' %}

{% block content %}
<h1>Delete post</h1>
<form action="" method="post">{% csrf_token %}
<p>Are you sure you want to delete "{{ post.title }}"?</p>
<input type="submit" value="Confirm">
</form>
{% endblock %}

新建视图类

修改blog/views.py文件,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
from django.views.generic import ListView, DetailView
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.urls import reverse_lazy
from .models import Post

class BlogListView(ListView):
model = Post
template_name = 'home.html'

class BlogDetailView(DetailView):
model = Post
template_name = 'post_detail.html'

class BlogCreateView(CreateView):
model = Post
template_name = 'post_new.html'
fields = '__all__'

class BlogUpdateView(UpdateView):
model = Post
template_name = 'post_edit.html'
fields = ['title', 'body']

class BlogDeleteView(DeleteView):
model = Post
template_name = 'post_delete.html'
# use reverse_lazy, it won't execute the
# URL redirect until the delete op finished
success_url = reverse_lazy('home')

更新路由

修改blog/urls.py文件,添加新的 URL 配置,代码如下:

1
2
3
4
5
6
7
8
9
10
11
from django.urls import path

from . import views

urlpatterns = [
path('', views.BlogListView.as_view(), name='home'),
path('post/<int:pk>/', views.BlogDetailView.as_view(), name='post_detail'),
path('post/new/', views.BlogCreateView.as_view(), name='post_new'),
path('post/<int:pk>/edit/', views.BlogUpdateView.as_view(), name='post_edit'),
path('post/<int:pk>/delete/', views.BlogDeleteView.as_view(), name='post_delete'),
]