上一节的注册中,使用了 form 表单,在 <form> 标签中,定义了 method 属性告诉浏览器想如何与服务器通信。HTTP 规范定义了几种 request methods 请求方法,需要使用 GET 和 POST。
Django 使用 CSRF Token 保护所有的 POST 请求,这是避免外部站点或者应用程序向服务器的应用程序提交数据的安全措施。
应用程序每次接收一个 POST 时,都先检查 CSRF Token,如果这个 request 没有 token,或者这个 token 是无效的,它就会抛弃提交的数据。
基于类的通用视图
from django.views.generic import UpdateView, ListView
① 主页
class BoardListView(ListView):
model = Board
context_object_name = 'boards'
template_name = 'board/home.html'
② 话题
class TopicListView(ListView):
model = Topic
context_object_name = 'topics'
template_name = 'board/topics.html'
paginate_by = 20
def get_context_data(self, **kwargs):
kwargs['board'] = self.board
return super().get_context_data(**kwargs)
def get_queryset(self):
self.board = get_object_or_404(Board, pk=self.kwargs.get('pk'))
queryset = self.board.topics.order_by('-last_updated').annotate(replies=Count('posts') - 1)
return queryset
③ 新建话题
Django 内置的视图装饰器,如果用户没有登录,将被重定向到登录页面。
from django.contrib.auth.decorators import login_required
@login_required
def new_topic(request, pk):
board = get_object_or_404(Board, pk=pk)
# 涉及到内容填写,都可以采用 form 表单
if request.method == "POST":
form = NewTopicForm(request.POST)
if form.is_valid():
topic = form.save(commit=False)
topic.board = board
topic.starter = request.user
topic.save()
post = Post.objects.create(
message=form.cleaned_data.get('message'),
topic=topic,
created_by=request.user
)
return redirect('users:topics', pk=board.pk)
else:
form = NewTopicForm()
return render(request, 'board/new_topic.html', {"board": board, "form": form})