You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 07:05:36