Django Girls教程问题:未登录用户可见编辑视图触发ValueError
问题描述
我正在学习Django并完成Django Girls教程。未登录状态下访问/post/18/时仍能看到编辑视图,点击保存会触发ValueError,希望未登录用户仅能查看文章内容,无法看到编辑视图。
相关代码
views.py
from django.shortcuts import render from django.utils import timezone from .models import Post from django.shortcuts import render, get_object_or_404 from .forms import PostForm from django.shortcuts import redirect # Create your views here. def post_list(request): posts= Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') return render(request, 'blog/post_list.html', {'posts' : posts}) def post_detail(request, pk): #Post.objects.get(pk=pk) post = get_object_or_404(Post, pk=pk) if request.method=='POST': form = PostForm(request.POST, instance=post) if form.is_valid(): post = form.save(commit=False) post.author = request.user post.published_date = timezone.now() post.save() return redirect('post_detail', pk=post.pk) else: form = PostForm(instance=post) return render(request, 'blog/post_edit.html', {'form':form}) def post_new(request): if request.method == "POST": form = PostForm(request.POST) if form.is_valid(): post = form.save(commit=False) post.author = request.user post.published_date = timezone.now() post.save() return redirect('post_detail', pk=post.pk) else: form = PostForm() return render(request, 'blog/post_edit.html', {'form': form}) def post_new(request): if request.method == "POST": form = PostForm(request.POST) if form.is_valid(): post = form.save(commit=False) post.author = request.user post.published_date = timezone.now() post.save() return redirect('post_detail', pk=post.pk) else: form = PostForm() return render(request, 'blog/post_edit.html', {'form': form}) def post_edit(request, pk): post = get_object_or_404(Post, pk=post.pk) if request.method == "POST": form = PostForm(request.POST, instance=post) if form.is_valid(): post = form.save(commit=False) post.author = request.user post.published_date = timezone.now() post.save() return redirect('post_detail', pk=post.pk) else: return render(request, 'blog/post_edit.html', {'form': form}) form = PostForm(instance=post) form = PostForm(request.POST, instance=post) form = PostForm(instance=post)
post_edit.html
{% extends 'blog/base.html' %} {% if user.is_authenticated %} {% block content %} <h2>New post</h2> <form method="POST" class="post-form">{% csrf_token %} {{ form.as_p }} <button type="submit" class="save btn btn-default">Save</button> </form> {% endblock %} {%endif%}
解决方案
1. 拆分视图职责,分离详情与编辑功能
当前post_detail视图同时承担展示和编辑功能,这是问题核心。修改post_detail让它只负责展示文章:
def post_detail(request, pk): post = get_object_or_404(Post, pk=pk) # 返回文章详情页面,不再处理编辑逻辑 return render(request, 'blog/post_detail.html', {'post': post})
2. 用login_required保护编辑视图
导入登录验证装饰器,给所有编辑相关视图添加验证,确保只有登录用户能访问:
# 先导入装饰器 from django.contrib.auth.decorators import login_required @login_required def post_new(request): if request.method == "POST": form = PostForm(request.POST) if form.is_valid(): post = form.save(commit=False) post.author = request.user post.published_date = timezone.now() post.save() return redirect('post_detail', pk=post.pk) else: form = PostForm() return render(request, 'blog/post_edit.html', {'form': form}) @login_required def post_edit(request, pk): # 修复参数错误:使用传入的pk而非post.pk post = get_object_or_404(Post, pk=pk) if request.method == "POST": form = PostForm(request.POST, instance=post) if form.is_valid(): post = form.save(commit=False) post.author = request.user post.published_date = timezone.now() post.save() return redirect('post_detail', pk=post.pk) else: form = PostForm(instance=post) return render(request, 'blog/post_edit.html', {'form': form})
3. 清理冗余代码
删除重复的post_new函数,以及post_edit视图末尾无效的重复代码。
4. 确认路由配置正确
确保urls.py中路由对应正确的视图:
from django.urls import path from . import views urlpatterns = [ path('', views.post_list, name='post_list'), path('post/<int:pk>/', views.post_detail, name='post_detail'), path('post/new/', views.post_new, name='post_new'), path('post/<int:pk>/edit/', views.post_edit, name='post_edit'), ]
5. 完善文章详情页面
创建或修改post_detail.html,只展示文章内容,登录用户可看到编辑入口:
{% extends 'blog/base.html' %} {% block content %} <div class="post"> {% if post.published_date %} <div class="date"> {{ post.published_date }} </div> {% endif %} {% if user.is_authenticated %} <a class="btn btn-default" href="{% url 'post_edit' pk=post.pk %}">编辑</a> {% endif %} <h1>{{ post.title }}</h1> <p>{{ post.text|linebreaksbr }}</p> </div> {% endblock %}
修改完成后,未登录用户访问文章详情页只能查看内容,无法进入编辑视图;点击保存的ValueError也会因登录拦截不再触发。
内容的提问来源于stack exchange,提问作者zip sim
相关产品推荐
相关产品推荐

